我尝试使用3维网格运行一个简单的程序,但由于某种原因,当我使用cuda-memcheck启动它时它会卡住,并且在超时后它终止。这个问题与短暂的超时无关,因为我将这种方式改为60秒。
我运行的代码有一个45x1575x1575的网格,它运行一个空的__global__
函数。我的计算能力是2.1,我使用标志-maxrregcount=24
进行编译,以限制设备功能可以使用的寄存器数量(在我的其他程序中看到它使用占用计算器可以获得最佳结果)
这是我的代码:
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
__global__ void stam(int a){
}
int main()
{
// Choose which GPU to run on, change this on a multi-GPU system.
cudaError_t cudaStatus = cudaSetDevice(0);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?");
return;
}
dim3 gridSize(45,1575,1575);
stam<<<gridSize,224>>>(4);
cudaStatus = cudaDeviceSynchronize(); // This function gets stuck
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaSetDevice failed!!");
return;
}
cudaStatus = cudaDeviceReset();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaDeviceReset failed!");
return 1;
}
return 0;
}
最大网格尺寸是否为65535x65535x65535?这里有什么问题?
编辑:当我用-G标志编译时它只会崩溃。否则它只是很慢,但它不会超过60秒。
答案 0 :(得分:2)
您的代码运行时间过长(是的,超过60秒)。
即使您的内核“什么都不做”,它仍然代表__global__
函数调用。为方便起见,编译器会生成大量的前导码。通常,编译器会优化大部分前导码,因为你的函数什么都不做(例如,它对传递给它的变量没有任何作用,前导码代码可以为每个线程提供。)但是当你传递-G
时切换,您几乎消除了所有编译器优化。通过将可执行文件和inspecting the code与cuobjdump -sass ...
一起使用,您可以了解每个线程块实际运行的代码的大小。
其次,使用cuda-memcheck
运行代码通常会增加执行时间。 cuda-memcheck
执行程序调整顺序并降低执行线程块的速率,因此它可以对每个线程块的内存访问模式进行全面分析,等等。
净效应是你的空内核调用,部分是由于非常大的网格(需要处理超过1亿个线程块),执行时间超过60秒。如果要验证这一点,请将TDR超时时间增加到5分钟或10分钟,最终您将看到程序正常返回。
在我的情况下,使用-G
和cuda-memcheck
,您的程序需要大约30秒才能在拥有11个SM的Quadro5000 GPU上运行。你的cc2.1 GPU可能有大约2个SM,因此比我的运行速度更慢。如果我在没有-G
开关的情况下编译,则运行时间会下降到大约2秒。如果我使用-G
开关进行编译,但在没有cuda-memcheck
的情况下运行,则大约需要4秒钟。如果我从内核中消除了int a
参数(这大大减少了前导代码),我可以使用-G
进行编译并使用cuda-memcheck
运行,只需要2秒。
包含-G
和int a
参数的内核机器代码:
Function : _Z4stami
.headerflags @"EF_CUDA_SM20 EF_CUDA_PTX_SM(EF_CUDA_SM20)"
/*0000*/ MOV R1, c[0x1][0x100]; /* 0x2800440400005de4 */
/*0008*/ ISUB R1, R1, 0x8; /* 0x4800c00020105d03 */
/*0010*/ S2R R0, SR_LMEMHIOFF; /* 0x2c000000dc001c04 */
/*0018*/ ISETP.GE.AND P0, PT, R1, R0, PT; /* 0x1b0e00000011dc23 */
/*0020*/ @P0 BRA 0x30; /* 0x40000000200001e7 */
/*0028*/ BPT.TRAP; /* 0xd00000000000c007 */
/*0030*/ IADD R0, R1, RZ; /* 0x48000000fc101c03 */
/*0038*/ MOV R2, R0; /* 0x2800000000009de4 */
/*0040*/ MOV R3, RZ; /* 0x28000000fc00dde4 */
/*0048*/ MOV R2, R2; /* 0x2800000008009de4 */
/*0050*/ MOV R3, R3; /* 0x280000000c00dde4 */
/*0058*/ MOV R4, c[0x0][0x4]; /* 0x2800400010011de4 */
/*0060*/ MOV R5, RZ; /* 0x28000000fc015de4 */
/*0068*/ IADD R2.CC, R2, R4; /* 0x4801000010209c03 */
/*0070*/ IADD.X R3, R3, R5; /* 0x480000001430dc43 */
/*0078*/ MOV32I R0, 0x20; /* 0x1800000080001de2 */
/*0080*/ LDC R0, c[0x0][R0]; /* 0x1400000000001c86 */
/*0088*/ IADD R2.CC, R2, RZ; /* 0x48010000fc209c03 */
/*0090*/ IADD.X R3, R3, RZ; /* 0x48000000fc30dc43 */
/*0098*/ MOV R2, R2; /* 0x2800000008009de4 */
/*00a0*/ MOV R3, R3; /* 0x280000000c00dde4 */
/*00a8*/ ST.E [R2], R0; /* 0x9400000000201c85 */
/*00b0*/ BRA 0xc8; /* 0x4000000040001de7 */
/*00b8*/ EXIT; /* 0x8000000000001de7 */
/*00c0*/ EXIT; /* 0x8000000000001de7 */
/*00c8*/ EXIT; /* 0x8000000000001de7 */
/*00d0*/ EXIT; /* 0x8000000000001de7 */
.........................
包含-G
但没有int a
参数的内核机器代码:
Function : _Z4stamv
.headerflags @"EF_CUDA_SM20 EF_CUDA_PTX_SM(EF_CUDA_SM20)"
/*0000*/ MOV R1, c[0x1][0x100]; /* 0x2800440400005de4 */
/*0008*/ BRA 0x20; /* 0x4000000040001de7 */
/*0010*/ EXIT; /* 0x8000000000001de7 */
/*0018*/ EXIT; /* 0x8000000000001de7 */
/*0020*/ EXIT; /* 0x8000000000001de7 */
/*0028*/ EXIT; /* 0x8000000000001de7 */
.........................
答案 1 :(得分:0)
我只是在cuda-memcheck和cuda-gdb下的C2050(功能2.0)上运行你的代码没有任何问题。这表明问题更可能与您的卡/设置有关,而不是代码本身。
如果您超出了功能,则应该获得启动错误代码,而不是挂起(如果您不确定,可以使用deviceQuery SDK代码检查最大尺寸)。
可能是cuda-memcheck试图获得对GPU的独占控制,并且正在使用其他东西进行超时[例如您的X服务器] - cuda-gdb是否更好用,这些工具是否适用于其他代码?