我正在尝试计算在一系列Conway的GOL中为n次迭代的pxq矩阵进行的转换次数。例如,给定1次迭代,初始状态为1闪烁(如下所示)。将有5个过渡(2个出生,1个存活,2个来自人口不足的死亡)。我已经有了这个工作,但我想将这个逻辑转换为使用CUDA运行。以下是我想要移植到CUDA的内容。
代码:
static void gol() // call this iterations x's
{
int[] tempGrid = new int[rows * cols]; // grid holds init conditions
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
tempGrid[i * cols + j] = grid[i * cols + j];
}
}
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
int numNeighbors = neighbors(i, j); // finds # of neighbors
if (grid[i * cols + j] == 1 && numNeighbors > 3)
{
tempGrid[i * cols + j] = 0;
overcrowding++;
}
else if (grid[i * cols + j] == 1 && numNeighbors < 2)
{
tempGrid[i * cols + j] = 0;
underpopulation++;
}
else if (grid[i * cols + j] == 1 && numNeighbors > 1)
{
tempGrid[i * cols + j] = 1;
survival++;
}
else if (grid[i * cols + j] == 0 && numNeighbors == 3)
{
tempGrid[i * cols + j] = 1;
birth++;
}
}
}
grid = tempGrid;
}
答案 0 :(得分:3)
您的主要减速将成为主内存访问。因此,我建议您根据可用的硬件选择较大的线程块大小。 256(16x16)是跨硬件兼容性的不错选择。这些线程块中的每一个都将计算板的略小部分的结果 - 如果您使用16x16,它们将计算板的14x14部分的结果,因为存在单个元素边界。 (使用16x16块来计算14x14块而不是16x16块的原因是用于内存读取合并。)
将董事会划分为(例如)14x14块;那就是你的网格(无论你认为合适,都有条理,但最有可能是board_width / 14
,board_height / 14
。
在内核中,让每个线程将其元素加载到共享内存中。然后syncthreads。然后让中间的14x14元素计算新值(使用存储在共享内存中的值)并将其写回全局内存。共享内存的使用有助于最小化全局读取和写入。这也是让你的线程块大小尽可能大的原因 - 边缘和角落是“浪费”全局内存访问,因为在那里获取的值只能使用1或3次,而不是9次。
答案 1 :(得分:0)
以下是您可以采取的一种方式: