0

我是 CUDA 的新手,目前正在优化现有的分子动力学应用程序。它的作用是使用带有坐标的 double4 数组并根据邻居列表计算力。我用以下几行编写了一个内核:

double4 mPos=d_arr_xyz[gid];
while(-1!=(id=d_neib_list[gid*MAX_NEIGHBORS+i])){
Calc(gid,mPos,AA,d_arr_xyz,id);i++;
}

然后 Calc 采用 d_arr_xyz[id] 并计算力。这会在每次调用 Calc 时读取 1 次 double4 + 65 次读取 (int +double4)(65 是每个粒子在 d_neib_list 中的平均邻居数(不等于 -1))。

是否有可能减少这些读取?不同粒子的邻居列表,即 d_arr_xyz[gid] 和 d_arr_xyz[id] 不相关,因此我不能将共享内存用于线程块来缓存 d_arr_xyz。

我看到的是,如果以某种方式在一个或几个大型事务中将整个列表 int*MAX_NEIGHBORS 加载到共享内存中,这将删除 65 个单独的 int 读取。

所以问题是:是否有可能这样做,以便将这 65 次 int 读取转换为几个大事务。我在文档中读到读取的长度甚至可以是 128 个字节。我到底应该写什么以便汇编程序进行 1 次大调用?

更新:

谢谢您的回复。从下面用户 talonmies 的答案中,我更改了替换邻居矩阵的维度 x 和 y 的代码。现在连续线程加载连续的 int[gid],我猜这可能会导致 128 字节的读取。该程序的运行速度提高了 8%。

4

1 回答 1

3

所有内存事务都是在每个 warp的基础上发布的(如果可能的话) 。因此,您要询问的 128 字节事务是当一个 warp 中的所有 32 个线程发出一条内存加载指令时,该指令可以在单个“合并”事务中提供服务。单个线程不能发出大内存事务,只有 32 个线程的 warp 可以,并且只有在您运行代码的任何架构的内存合并要求能够得到满足时。

我无法真正遵循您对代码实际执行的描述,但仅从第一原则来看,答案似乎是否定的。

于 2013-06-30T11:58:12.457 回答