这个问题是关于cuda的堆大小限制。 访问过有关此主题的一些问题,包括以下问题: new operator in kernel .. strange behaviour 我做了一些测试。鉴于内核如下:
#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;
}
我想测试堆大小限制。
编辑2:如何分配设备范围的变量一次但是所有线程都可写(不是来自主机,使用设备代码中的动态分配)?
答案 0 :(得分:2)
可能您没有在new
操作上测试返回的空指针,这是一个valid method in C++ for the operator to report a failure。
当我按如下方式修改你的代码时,我收到消息“第二次新的失败”:
#include <stdio.h>
#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];
if (temp == 0) {printf("first new failed\n"); return;}
temp2 = new double[NP];
if (temp2 == 0) {printf("second new failed\n"); return;}
}
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() {
test<<<1,1>>>();
cudaDeviceSynchronize();
return 0;
}
如果您提供完整的,可编译的代码,供其他人使用,就像我一样,这很方便。
对于您的第一个EDIT问题,如果删除第一个新内容,第二个新内容将起作用就不足为奇了。第一个几乎分配了所有可用的8MB。如果删除该分配,则第二个将成功。参考documentation,我们看到以这种方式动态分配的内存在cuda上下文的整个生命周期中存在,或直到执行相应的删除操作(即不仅仅是单个内核调用。内核的完成)不一定免费分配。)
对于您的第二个EDIT问题,您已经使用__device__ double *temp;
指针演示了一个方法,一个线程可以通过该指针分配所有线程都可以访问的存储。但是,跨块会出现问题,因为无法保证块之间的同步顺序或块之间的执行顺序,因此如果从块0中的线程0分配,则仅在块0在其他块之前执行时才有用。您可以想出一个复杂的方案来检查变量分配是否已经完成(可能通过测试指针为NULL,也可能使用原子),但它会创建脆弱的代码。最好提前规划全局分配并从主机进行相应分配。