- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用 PyCuda 开发遗传元胞自动机。每个细胞都会有大量的基因组数据,以及细胞参数。我想知道什么是最有效的方法来 1) 将单元格数据传递给 CUDA 内核,然后 2) 处理这些数据。
我从一个特别糟糕的 (imo),但仍然有效的解决方案开始。它在单独的数组中传递每个参数,然后使用 switch-case 和大量重复代码处理它们。
然后,我意识到我很快就会以每个内核函数的大量参数结束,并决定重写它。
第二种解决方案是将所有单元格参数存储在具有额外维度的单个数组中。这在代码中要优雅得多,但令人惊讶的是代码运行速度慢了 10 倍!
为了更清楚,我需要为每个单元格存储的完整数据列表:
我将一个自动机步骤分成两个阶段。首先(发射阶段)是为每个细胞邻居计算(Fi,Mi,Ti)。第二个(吸收阶段)是将 8x(Fi, Mi, Ti) 值与当前细胞状态混合。尚未实现基因组或寄存器,但我需要它的数据以备将来使用。
所以,我的第一个解决方案的代码是:
Mk = 64
Tk = 1000
emit_gpu = ElementwiseKernel("int3 *cells, int3 *dcells0, int3 *dcells1, int3 *dcells2, int3 *dcells3, int3 *dcells4, int3 *dcells5, int3 *dcells6, int3 *dcells7, int w, int h", """
int x = i / h;
int y = i % h;
int3 cell = cells[i];
float M = (float) cell.y;
float T = (float) cell.z;
int Mi = (int) (fmin(1, T / Tk) * M);
cells[i].y -= Mi;
cells[i].z -= (int) (T * fmin(1, T / Tk) / 1);
int Fi = cell.x;
int Mbase = Mi / 8;
int Mpart = Mi % 8;
int Madd;
int Ti = cell.z;
int ii, xo, yo;
for (int cc = 0; cc < 9; cc++) {
int c = (cc + Fi) % 9;
if (c == 4) continue;
xo = x + c%3 - 1;
if (xo < 0) xo = w + xo;
if (xo >= w) xo = xo - w;
yo = y + c/3 - 1;
if (yo < 0) yo = h + yo;
if (xo >= w) yo = yo - h;
ii = xo * h + yo;
if (Mpart > 0) { Madd = 1; Mpart--;} else Madd = 0;
switch(c) {
case 0: dcells0[ii] = make_int3(Fi, Mbase + Madd, Ti); break;
case 1: dcells1[ii] = make_int3(Fi, Mbase + Madd, Ti); break;
case 2: dcells2[ii] = make_int3(Fi, Mbase + Madd, Ti); break;
case 3: dcells3[ii] = make_int3(Fi, Mbase + Madd, Ti); break;
case 5: dcells4[ii] = make_int3(Fi, Mbase + Madd, Ti); break;
case 6: dcells5[ii] = make_int3(Fi, Mbase + Madd, Ti); break;
case 7: dcells6[ii] = make_int3(Fi, Mbase + Madd, Ti); break;
case 8: dcells7[ii] = make_int3(Fi, Mbase + Madd, Ti); break;
default: break;
}
}
""", "ca_prepare", preamble="""
#define Tk %s
""" % Tk)
absorb_gpu = ElementwiseKernel("int3 *cells, int3 *dcells0, int3 *dcells1, int3 *dcells2, int3 *dcells3, int3 *dcells4, int3 *dcells5, int3 *dcells6, int3 *dcells7, int *img, int w, int h", """
int3 cell = cells[i];
int3 dcell = dcells0[i];
cell = cell + calc_d(cell.x, cell.y, cell.z, dcell.x, dcell.y, dcell.z);
cell.x = cell.x % 360;
if (cell.x < 0) cell.x += 360;
dcell = dcells1[i];
cell = cell + calc_d(cell.x, cell.y, cell.z, dcell.x, dcell.y, dcell.z);
cell.x = cell.x % 360;
if (cell.x < 0) cell.x += 360;
if (cell.z > Tk) cell.z = Tk;
dcell = dcells2[i];
cell = cell + calc_d(cell.x, cell.y, cell.z, dcell.x, dcell.y, dcell.z);
cell.x = cell.x % 360;
if (cell.x < 0) cell.x += 360;
if (cell.z > Tk) cell.z = Tk;
dcell = dcells3[i];
cell = cell + calc_d(cell.x, cell.y, cell.z, dcell.x, dcell.y, dcell.z);
cell.x = cell.x % 360;
if (cell.x < 0) cell.x += 360;
if (cell.z > Tk) cell.z = Tk;
dcell = dcells4[i];
cell = cell + calc_d(cell.x, cell.y, cell.z, dcell.x, dcell.y, dcell.z);
cell.x = cell.x % 360;
if (cell.x < 0) cell.x += 360;
if (cell.z > Tk) cell.z = Tk;
dcell = dcells5[i];
cell = cell + calc_d(cell.x, cell.y, cell.z, dcell.x, dcell.y, dcell.z);
cell.x = cell.x % 360;
if (cell.x < 0) cell.x += 360;
if (cell.z > Tk) cell.z = Tk;
dcell = dcells6[i];
cell = cell + calc_d(cell.x, cell.y, cell.z, dcell.x, dcell.y, dcell.z);
cell.x = cell.x % 360;
if (cell.x < 0) cell.x += 360;
if (cell.z > Tk) cell.z = Tk;
dcell = dcells7[i];
cell = cell + calc_d(cell.x, cell.y, cell.z, dcell.x, dcell.y, dcell.z);
cell.x = cell.x % 360;
if (cell.x < 0) cell.x += 360;
if (cell.z > Tk) cell.z = Tk;
cells[i] = cell;
img[i] = hsv2rgb(cell);
""", "ca_calc", preamble="""
#include <math.h>
#define Mk %s
#define Tk %s
__device__ int3 operator+(const int3 &a, const int3 &b) {
return make_int3(a.x+b.x, a.y+b.y, a.z+b.z);
}
__device__ int3 calc_d(int Fc, int Mc, int Tc, int Fi, int Mi, int Ti) {
int dF = Fi - Fc;
if (dF > 180) Fc += 360;
if (dF < -180) Fc -= 360;
float sM = Mi + Mc;
if (sM != 0) sM = Mi / sM; else sM = 0;
dF = (int) (Fi - Fc) * sM;
int dM = Mi;
int dT = fabs((float) (Fi - Fc)) * fmin((float) Mc, (float) Mi) / Mk + (Ti - Tc) * sM;
return make_int3(dF, dM, dT);
}
__device__ uint hsv2rgb(int3 pixel) {
// skipped for brevity
}
""" % (Mk, Tk, RAM))
第二个和当前的解决方案:
Mk = 64
Tk = 1000
CELL_LEN = 120 # number of parameters per cell
emit_gpu = ElementwiseKernel("int *cells, int w, int h", """
int x = i / h;
int y = i % h;
int ii = i * CN;
int Fc = cells[ii];
int Mc = cells[ii+1];
int Tc = cells[ii+2];
float M = (float) Mc;
float T = (float) Tc;
int Mi = (int) (fmin(1, T / Tk) * M);
cells[ii+1] = Mc - Mi;
cells[ii+2] = Tc - (int) (T * fmin(1, T / Tk));
int Mbase = Mi / 8;
int Mpart = Mi % 8;
int Madd;
int iii, xo, yo;
for (int cc = 0; cc < 9; cc++) {
int c = (cc + Fc) % 9;
if (c == 4) continue;
xo = x + c%3 - 1;
if (xo < 0) xo = w + xo; else if (xo >= w) xo = xo - w;
yo = y + c/3 - 1;
if (yo < 0) yo = h + yo; else if (xo >= w) yo = yo - h;
if (Mpart > 0) { Madd = 1; Mpart--;} else Madd = 0;
if (c > 4) c--;
iii = (xo * h + yo) * CN + 6 + c*3;
cells[iii] = Fc;
cells[iii+1] = Mbase + Madd;
cells[iii+2] = Tc;
}
""", "ca_emit", preamble="""
#define Tk %s
#define CN %s
""" % (Tk, CELL_LEN))
absorb_gpu = ElementwiseKernel("int *cells, int *img, int w, int h", """
int ii = i * CN;
int Fc = cells[ii];
int Mc = cells[ii+1];
int Tc = cells[ii+2];
for (int c=0; c < 8; c++){
int iii = ii + c * 3 + 6;
int Fi = cells[iii];
int Mi = cells[iii+1];
int Ti = cells[iii+2];
int dF = Fi - Fc;
if (dF > 180) Fc += 360;
if (dF < -180) Fc -= 360;
float sM = Mi + Mc;
if (sM != 0) sM = Mi / sM; else sM = 0;
dF = (int) (Fi - Fc) * sM;
int dM = Mi;
int dT = fabs((float) (Fi - Fc)) * fmin((float) Mc, (float) Mi) / Mk + (Ti - Tc) * sM;
Fc += dF;
Mc += dM;
Tc += dT;
Fc = Fc % 360;
if (Fc < 0) Fc += 360;
if (Tc > Tk) Tc = Tk;
}
cells[ii] = Fc;
cells[ii+1] = Mc;
cells[ii+2] = Tc;
cells[ii+18] = (cells[ii+18] + 1) % 8;
img[i] = hsv2rgb(Fc, Tc, Mc);
""", "ca_absorb", preamble="""
#include <math.h>
#define Mk %s
#define Tk %s
#define CN %s
__device__ uint hsv2rgb(int hue, int sat, int val) {
// skipped for brevity
}
""" % (Mk, Tk, CELL_LEN))
两种变体产生完全相同的 CA 行为,但后者运行速度要慢得多。
GTX 泰坦:
GT 630M:
如果需要,请随意使用这两种解决方案:
欢迎任何线索或建议:
最佳答案
好的,我设法将第二个解决方案的运行速度提高了将近 15 倍。进行了以下更改:
int
转换为int4
。这使得它比使用 int3
的解决方案更快。虽然,额外的空间未被使用(.w 维度)。 [3 倍加速]优化后的代码如下:
Mk = 64
Tk = 1000
emit_gpu = ElementwiseKernel("int4 *cells, int w, int h, int cn", """
int x = i / h;
int y = i % h;
int4 cell = cells[i];
int Fc = cell.x;
int Mc = cell.y;
int Tc = cell.z;
float M = (float) Mc;
float T = (float) Tc;
int Mi = (int) (fmin(1, T / Tk) * M);
cells[i] = make_int4(Fc, Mc - Mi, Tc - (int) (T * fmin(1, T / Tk)), 0);
int Mbase = Mi / 8;
int Mpart = Mi % 8;
int Madd;
int ii;
int xo, yo;
int cnn = 0;
for (int dx = -1; dx < 2; dx++) {
xo = x + dx;
if (xo < 0) xo = w + xo; else if (xo >= w) xo = xo - w;
for (int dy = -1; dy < 2; dy++) {
if (dx == 0 && dy == 0) continue;
cnn += cn;
yo = y + dy;
if (yo < 0) yo = h + yo; else if (yo >= h) yo = yo - h;
if (Mpart > 0) { Madd = 1; Mpart--;} else Madd = 0;
ii = (xo * h + yo) + cnn;
cells[ii] = make_int4(Fc, Mbase + Madd, Tc, 0);
}
}
""", "ca_emit", preamble="""
#define Tk %s
#define CN %s
""" % (Tk, CELL_LEN))
absorb_gpu = ElementwiseKernel("int4 *cells, int *img, int w, int h, int cn", """
int ii = i;
int4 cell = cells[i];
int Fc = cell.x;
int Mc = cell.y;
int Tc = cell.z;
for (int c=0; c < 8; c++){
ii += cn;
cell = cells[ii];
int Fi = cell.x;
int Mi = cell.y;
int Ti = cell.z;
int dF = Fi - Fc;
if (dF > 180) Fc += 360;
if (dF < -180) Fc -= 360;
float sM = Mi + Mc;
if (sM != 0) sM = Mi / sM; else sM = 0;
dF = (int) (Fi - Fc) * sM;
int dM = Mi;
int dT = fabs((float) (Fi - Fc)) * fmin((float) Mc, (float) Mi) / Mk + (Ti - Tc) * sM;
Fc += dF;
Mc += dM;
Tc += dT;
Fc = Fc % 360;
if (Fc < 0) Fc += 360;
if (Tc > Tk) Tc = Tk;
}
cells[i] = make_int4(Fc, Mc, Tc, 0);
img[i] = hsv2rgb(Fc, Tc, Mc);
""", "ca_absorb", preamble="""
#include <math.h>
#define Mk %s
#define Tk %s
__device__ uint hsv2rgb(int hue, int sat, int val) {
// skipped for brevity
}
""" % (Mk, Tk))
感谢 Park Young-Bae 提供重新打包的线索,也感谢 Alexey Shchepin 解决一些优化问题。
关于python - 使用 PyCuda 的遗传细胞自动机,如何有效地将每个细胞的大量数据传递给 CUDA 内核?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27500963/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!