我在3D中有一个连接的N个对象(原子)的“字符串”(分子)(每个原子都有一个坐标)。我需要计算分子中每对原子之间的距离(参见下面的伪代码)。如何用CUDA完成?我应该转到内核函数2 3D阵列吗?或3个坐标为X [N],Y [N],Z [N]的数组?感谢。
struct atom { double x,y,z; }
int main()
{
//N number of atoms in a molecule
double DistanceMatrix[N][N];
double d;
atom Atoms[N];
for (int i = 0; i < N; i ++)
for (int j = 0; j < N; j++)
DistanceMatrix[i][j] = (atoms[i].x -atoms[j].x)*(atoms[i].x -atoms[j].x) +
(atoms[i].y -atoms[j].y)* (atoms[i].y -atoms[j].y) + (atoms[i].z -atoms[j].z)* (atoms[i].z -atoms[j].z;
}
答案 0 :(得分:1)
除非您使用非常大的分子,否则可能没有足够的工作来保持GPU的繁忙,因此CPU的计算速度会更快。
如果您打算计算欧几里德距离,则计算结果不正确。你需要毕达哥拉斯定理的3D版本。
我会使用SoA来存储坐标。
您希望生成具有尽可能多的合并读取和写入的内存访问模式。为此,安排由每个warp中的32个线程生成的地址或索引尽可能彼此接近(稍微简化)。
threadIdx
指定块内的线程索引,blockIdx
指定网格中的块索引。对于warp中的所有线程,blockIdx
始终是相同的。只有threadIdx
在块中的线程内有所不同。为了可视化如何将threadIdx
的3维分配给线程,请将它们视为嵌套循环,其中x
是内循环,z
是外循环。因此,具有相邻x
值的线程最有可能位于同一个warp中,如果x
可被32整除,则只有共享相同x / 32
值的线程在同一个warp中
我在下面列出了一个完整的算法示例。在示例中,i
索引是从threadIdx.x
派生的,因此,为了检查warp是否会生成合并读取和写入,我会在插入一些连续值(例如0,1和0)时检查代码。 2为i
并检查生成的索引是否也是连续的。
从j
索引生成的地址不太重要,因为j
来自threadIdx.y
,因此在变形内变化的可能性较小(如果{{1}则不会变化可以被32)整除。
threadIdx.x