这个问题是关于 cuda 中的堆大小限制。访问了一些关于这个主题的问题,包括这个: 内核中的新运算符..奇怪的行为 我做了一些测试。给定一个内核如下:
#include <cuda.h>
#include <cuda_runtime.h>
#define CUDA_CHECK( err ) __cudaSafeCall( err, __FILE__, __LINE__ )
#define CUDA_CHECK_ERROR() __cudaCheckError( __FILE__, __LINE__ )
inline void __cudaSafeCall( cudaError err, const char *file, const int line )
{
if ( cudaSuccess != err )
{
fprintf( stderr, "cudaSafeCall() failed at %s:%i : %s\n",
file, line, cudaGetErrorString( err ) );
exit( -1 );
}
return;
}
inline void __cudaCheckError( const char *file, const int line )
{
cudaError err = cudaGetLastError();
if ( cudaSuccess != err )
{
fprintf( stderr, "cudaCheckError() failed at %s:%i : %s\n",
file, line, cudaGetErrorString( err ) );
exit( -1 );
}
return;
}
#include <stdio>
#define NP 900000
__device__ double *temp;
__device__ double *temp2;
__global__
void test(){
int i = blockDim.x*blockIdx.x + threadIdx.x;
if(i==0){
temp = new double[NP];
//temp2 = new double[NP];
}
if(i==0){
for(int k=0;k<NP;k++){
temp[i] = 1.;
if(k%1000 == 0){
printf("%d : %g\n", k, temp[i]);
}
}
}
if(i==0){
delete(temp);
//delete(temp2);
}
}
int main(){
//cudaDeviceSetLimit(cudaLimitMallocHeapSize, 32*1024*1024);
//for(int k=0;k<2;k++){
test<<<ceil((float)NP/512), 512>>>();
CUDA_CHECK_ERROR();
//}
return 0;
}
我想测试堆大小限制。
- 使用一个线程动态分配一个数组(临时),其大小大约超过 960,000*sizeof(double)(接近 8MB,这是堆大小的默认限制)会产生错误:好的。900,000 件作品。(有人知道如何计算真正的极限吗?)
- 提高堆大小限制允许分配更多内存:正常,好的。
- 回到 8MB 堆大小,为每个线程分配一个数组和两个线程(因此,将 if (i==0) 替换为 if(i==0 || i==1),每个 900,000 * sizeof(double) 失败. 但是每个 450,000*sizeof(double) 都可以。仍然可以。
- 我的问题来了:用一个线程分配两个数组(因此,线程 0 的 temp 和 temp2),每个 900,000 * sizeof(double) 也可以,但它不应该吗?事实上,当我尝试在两个数组中写入时,它都会失败。但是任何人都有一个想法,为什么在使用带有一个线程的两个数组而不是带有两个线程的两个数组时会出现这种不同的分配行为?
编辑:另一个测试,我觉得对于像我一样学习堆使用的人来说很有趣: 5. 执行内核两次,一个大小为 900,000 * sizeof(double) 的数组由单线程 0 分配,如果有删除工作。如果 delete 省略,第二次会失败,但会执行第一次调用。
编辑 2:如何分配设备范围的变量一次但可由所有线程写入(不是来自主机,在设备代码中使用动态分配)?