Cuda 从全局内存加载
假设这样的简单内核:Cuda 从全局内存加载,cuda,Cuda,假设这样的简单内核: __global__ void fg(struct s_tp tp, struct s_param p) { const uint bid = blockIdx.y * gridDim.x + blockIdx.x; const uint tid = threadIdx.x; const uint idx = bid * blockDim.x + tid; if(idx >= p.ntp) return; double3 r = tp.rh
__global__ void fg(struct s_tp tp, struct s_param p)
{
const uint bid = blockIdx.y * gridDim.x + blockIdx.x;
const uint tid = threadIdx.x;
const uint idx = bid * blockDim.x + tid;
if(idx >= p.ntp) return;
double3 r = tp.rh[idx];
double d = sqrt(r.x*r.x + r.y*r.y + r.z*r.z);
tp.d[idx] = d;
}
__global__ void fg(struct s_tp tp, double* s_tp_rx, double* s_tp_ry, double* s_tp_rz, double* s_tp_d, struct s_param p)
{
const uint bid = blockIdx.y * gridDim.x + blockIdx.x;
const uint tid = threadIdx.x;
const uint idx = bid * blockDim.x + tid;
if(idx >= p.ntp) return;
double rx = s_tp_rx[idx];
double ry = s_tp_ry[idx];
double rz = s_tp_rz[idx];
double d = sqrt(rx*rx + ry*ry + rz*rz);
s_tp_d[idx] = d;
}
这是真的吗
double3 r = tp.rh[idx];
- 数据从全局内存加载到r变量中
- r存储在寄存器中,或者如果有许多变量,则存储在本地内存中
- r不存储在共享内存中
- 计算d,然后将d写回全局内存
- 寄存器比其他存储器快
- 如果寄存器空间已满(一些大内核),则会使用本地内存,访问速度会变慢
- 当我需要双打时,有没有办法加快速度?例如,首先将数据加载到共享内存中,然后对其进行操作
谢谢大家。是的,几乎都是真的 •当我需要双打时,有没有办法加快速度?例如,首先将数据加载到共享内存中,然后对其进行操作 如果存在数据重用(多次加载同一数据项,通常由threadblock中的多个线程加载),或者可能在专门使用共享内存以帮助全局合并时(例如在执行任务时),使用共享内存非常有用 数据重用意味着您多次使用(加载)数据,为了使共享内存有用,它意味着您通过多个线程多次加载数据。如果您在一个线程中多次使用它,那么单次加载加上将其存储在寄存器中的编译器(自动)“优化”就是您所需要的 编辑 @Jez给出的答案对优化负载有一些好的想法。我建议另一个想法是将AoS数据存储方案转换为SoA方案。数据存储转换是提高CUDA代码速度的常用方法 您的
s_tp
struct(您没有显示)似乎具有存储每个项目/结构的多个double
数量的存储空间。如果您为这些数量中的每一个创建单独的阵列,您将有机会实现最佳加载/存储。大概是这样的:
__global__ void fg(struct s_tp tp, struct s_param p)
{
const uint bid = blockIdx.y * gridDim.x + blockIdx.x;
const uint tid = threadIdx.x;
const uint idx = bid * blockDim.x + tid;
if(idx >= p.ntp) return;
double3 r = tp.rh[idx];
double d = sqrt(r.x*r.x + r.y*r.y + r.z*r.z);
tp.d[idx] = d;
}
__global__ void fg(struct s_tp tp, double* s_tp_rx, double* s_tp_ry, double* s_tp_rz, double* s_tp_d, struct s_param p)
{
const uint bid = blockIdx.y * gridDim.x + blockIdx.x;
const uint tid = threadIdx.x;
const uint idx = bid * blockDim.x + tid;
if(idx >= p.ntp) return;
double rx = s_tp_rx[idx];
double ry = s_tp_ry[idx];
double rz = s_tp_rz[idx];
double d = sqrt(rx*rx + ry*ry + rz*rz);
s_tp_d[idx] = d;
}
对于类似类型的使用模式,这种方法可能在设备代码的其他地方也有好处。这都是真的
当我需要双打时,有没有办法加快速度?例如负载
数据首先进入共享内存,然后再进行操作
对于您给出的示例,您的实现可能不是最优的。您应该做的第一件事是将获得的带宽与参考内核的带宽进行比较,例如,cudaMemcpy。如果差距很大,并且您将从缩小差距中获得显著的加速,则可以进行优化
看看您的内核,我觉得有两件事可能不太理想:
虽然为每个线程添加更多的工作是一件相当简单的事情,但是为解决方案优化内存访问模式(不改变数据类型)就不那么简单了。幸运的是,有些库可以提供帮助。我认为,使用,特别是集体,应该让您能够更有效地加载。例如,通过使用转置操作符在每个线程中加载6个
double
项,您可以在每个线程中处理两个元素,将它们打包成double2
,并正常存储它们。double3 v用于什么?它被分配了一个值,之后就再也不用了。你的陈述似乎很准确。因为每个线程都从tp.rh
读取自己的值,所以读取到共享内存中并没有任何好处。通过在一个线程中处理多个数组元素,您可以稍微加快内核的速度。我忘了删除它。现在没事了。