Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cuda 从全局内存加载_Cuda - Fatal编程技术网

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。如果差距很大,并且您将从缩小差距中获得显著的加速,则可以进行优化

看看您的内核,我觉得有两件事可能不太理想:

  • 每个线程没有多少工作。如果可能,每个线程处理多个元素可以提高性能。这在一定程度上是因为它避免了线程初始化/删除开销
  • 从double3加载不如从其他类型加载有效。加载数据的最佳方式通常是每个线程使用128位加载。加载三个连续的64位值会比较慢,可能不会太慢,但仍然会比较慢 编辑:Robert Crovella下面的回答为第二点提供了一个很好的解决方案,这一点需要改变数据类型。出于某种原因,我原本认为这不是一个选项,因此,如果您只是更改数据类型,下面的解决方案可能是过头了


    虽然为每个线程添加更多的工作是一件相当简单的事情,但是为解决方案优化内存访问模式(不改变数据类型)就不那么简单了。幸运的是,有些库可以提供帮助。我认为,使用,特别是集体,应该让您能够更有效地加载。例如,通过使用转置操作符在每个线程中加载6个
    double
    项,您可以在每个线程中处理两个元素,将它们打包成
    double2
    ,并正常存储它们。

    double3 v用于什么?它被分配了一个值,之后就再也不用了。你的陈述似乎很准确。因为每个线程都从
    tp.rh
    读取自己的值,所以读取到共享内存中并没有任何好处。通过在一个线程中处理多个数组元素,您可以稍微加快内核的速度。我忘了删除它。现在没事了。