CUDA:curand_统一全局内存对齐

CUDA:curand_统一全局内存对齐,c,random,cuda,C,Random,Cuda,在分析一个项目时,我注意到对curand\u uniform的调用在全局内存访问方面存在问题。例如,使用内核创建的随机数生成器,如下所示: __device__ curandState randGPU_d_state[200000]; __global__ void initCurand(const unsigned long seed) { int i = blockIdx.x * blockDimx. + threadIdx.x; if (i < 200000) cu

在分析一个项目时,我注意到对
curand\u uniform
的调用在
全局内存访问方面存在问题。例如,使用内核创建的
随机数生成器
,如下所示:

__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]);
}
当分析
'Global Memory Access Pattern'
'Global Load L2 Transactions/Access=31.8,Ideal Transactions/Access=8[12000个L2事务,总共执行377次]”时,导致
NVIDIA Visual Profiler
抛出这一行

事实上,我在同一条线上收到了7条这样的警告

此外,如果我改用
curand_normal
,NVIDIA Visual Profiler还会警告
curand_normal.h
的第310、312、313、315和316行出现问题,并且
理想事务/访问
的比率为4/8


我相信我正在访问合并的状态(虽然我没有在它里面打结内存的细节,但仍然在访问合并的状态变量),因此,为什么这些坏比率是预设的?

您关于合并内存访问的假设是不正确的。如果您运行类似这样的操作:

#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;
}
#包括
#包括
#包括
#包括
__设备管理州和GPU d_州[200000];
__全局无效
initCurand()
{
printf(“%ld\n”,sizeof(randGPU_d_state[0]);
}
int main()
{
initCurand();
cudaDeviceReset();
返回0;
}

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

你能在其中添加一个更明确的问题吗?我明白了,所以这是不可避免的?在使用curand库时,我无法摆脱这个问题?@James:是的,如果你想在全局内存中存储和访问大量这样的随机生成器状态,这是不可避免的。但你为什么要这么做还不清楚。我看不出有必要这样做的用例,也许我用了错误的方法。我相信两者都使用了类似的方法,尽管它们没有声明
randGPU状态[200000]
而是声明为指针,然后声明
cudaMalloc((void**)和randGPU状态/Synapses,2000*sizeof(curandState))
#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;
}