【问题标题】:CUDA: curand_uniform Global Memory AlignmentCUDA:curand_uniform 全局内存对齐
【发布时间】:2015-12-14 08:34:45
【问题描述】:

分析一个项目,我注意到对curand_uniform 的调用与global memory access 存在问题。例如使用内核创建的random number generator,如下所示:

__device__ curandState randGPU_d_state[200000];

__global__ void
initCurand(const unsigned long seed)
{
  int i = blockIdx.x * blockDimx. + threadIdx.x;
  if (i < 200000)
    curand_init(seed, i, 0, &randGPU_d_state[i]);
}

稍后在后续内核中通过以下方式访问,其中threadIdx.x &lt; 200000

float temp = curand_uniform(&randGPU_d_state[threadIdx.x]);

在将'Global Memory Access Pattern' 分析为'Global Load L2 Transactions/Access = 31.8, Ideal Transactions/Access = 8[ 12000 L2 transactions for 377 total executions ] ' 时,导致NVIDIA Visual Profiler 抛出此行。

事实上,我在同一行收到了 7 个这样的警告。

此外,如果我改用curand_normal,NVIDIA Visual Profiler 还会警告curand_normal.h 的第 310、312、313、315 和 316 行存在问题,Ideal Transactions/Access 的错误比率为 4 of 8。

我相信我正在访问合并的状态(虽然我没有将内存的细节打结在其中,但仍然访问了合并的状态变量),因此,为什么要预设这些不良比率?

【问题讨论】:

  • 你能在其中的某处添加一个更明确的问题吗?

标签: c random cuda


【解决方案1】:

您对合并内存访问的假设是不正确的。如果你运行这样的东西:

#include <stdio.h> 
#include <stdlib.h> 
#include <cuda.h> 
#include <curand_kernel.h> 

__device__ curandState randGPU_d_state[200000];

__global__ void
initCurand()
{
    printf("%ld\n", sizeof(randGPU_d_state[0]));
}

int main()
{
    initCurand<<<1,1>>>();
    cudaDeviceReset();
    return 0;
}

您会看到它为 sizeof(curandState) 打印 48。我不知道可以完全合并访问这么大的类型数组。

【讨论】:

  • 我明白了,所以这是不可避免的?使用 curand 库时我无法摆脱这个问题?
  • @James:是的,如果你想在全局内存中存储和访问大量随机生成器状态,这是不可避免的。但不清楚为什么您需要这样做。我看不到有必要这样做的用例
  • 也许我的做法是错误的。我相信thisthis 都使用类似的方法,尽管它们不是声明randGPU_d_state[200000],而是声明为指针,然后声明为cudaMalloc((void**) &amp;randGPU_d_state_Synapses, 2000 * sizeof(curandState));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-09
相关资源
最近更新 更多