用于多个gpu的CUDADeviceSet';s

用于多个gpu的CUDADeviceSet';s,cuda,Cuda,我目前正在一个gpu服务器上工作,它有4个特斯拉T10 gpu。虽然我一直在测试内核,并且必须经常使用ctrl-C终止进程,但我在一个简单的设备查询代码的末尾添加了几行代码。代码如下: #include <stdio.h> // Print device properties void printDevProp(cudaDeviceProp devProp) { printf("Major revision number: %d\n", devProp

我目前正在一个gpu服务器上工作,它有4个特斯拉T10 gpu。虽然我一直在测试内核,并且必须经常使用ctrl-C终止进程,但我在一个简单的设备查询代码的末尾添加了几行代码。代码如下:

#include <stdio.h>

 // Print device properties
 void printDevProp(cudaDeviceProp devProp)
{
    printf("Major revision number:         %d\n",  devProp.major);
    printf("Minor revision number:         %d\n",  devProp.minor);
    printf("Name:                          %s\n",  devProp.name);
    printf("Total global memory:           %u\n",  devProp.totalGlobalMem);
    printf("Total shared memory per block: %u\n",  devProp.sharedMemPerBlock);
    printf("Total registers per block:     %d\n",  devProp.regsPerBlock);
    printf("Warp size:                     %d\n",  devProp.warpSize);
    printf("Maximum memory pitch:          %u\n",  devProp.memPitch);
    printf("Maximum threads per block:     %d\n",  devProp.maxThreadsPerBlock);
    for (int i = 0; i < 3; ++i)
    printf("Maximum dimension %d of block:  %d\n", i, devProp.maxThreadsDim[i]);
    for (int i = 0; i < 3; ++i)
    printf("Maximum dimension %d of grid:   %d\n", i, devProp.maxGridSize[i]);
    printf("Clock rate:                    %d\n",  devProp.clockRate);
    printf("Total constant memory:         %u\n",  devProp.totalConstMem);
    printf("Texture alignment:             %u\n",  devProp.textureAlignment);
    printf("Concurrent copy and execution: %s\n",  (devProp.deviceOverlap ? "Yes" : "No"));
    printf("Number of multiprocessors:     %d\n",  devProp.multiProcessorCount);
    printf("Kernel execution timeout:      %s\n",  (devProp.kernelExecTimeoutEnabled ? "Yes" : "No"));
    return;
}

 int main()
{
    // Number of CUDA devices
    int devCount;
    cudaGetDeviceCount(&devCount);
    printf("CUDA Device Query...\n");
    printf("There are %d CUDA devices.\n", devCount);

    // Iterate through devices
    for (int i = 0; i < devCount; ++i)
    {
        // Get device properties
        printf("\nCUDA Device #%d\n", i);
        cudaDeviceProp devProp;
        cudaGetDeviceProperties(&devProp, i);
        printDevProp(devProp);
    }

    printf("\nPress any key to exit...");
    char c;
    scanf("%c", &c);

    **for (int i = 0; i < devCount; i++) {
        cudaSetDevice(i);
        cudaDeviceReset();
    }**

    return 0;
}
#包括
//打印设备属性
作废打印devProp(cudaDeviceProp devProp)
{
printf(“主要修订号:%d\n”,devProp.Major);
printf(“次要修订号:%d\n”,devProp.Minor);
printf(“名称:%s\n”,devProp.Name);
printf(“总全局内存:%u\n”,devrop.totalGlobalMem);
printf(“每个块的总共享内存:%u\n”,devrop.SharedTemperBlock);
printf(“每个块的寄存器总数:%d\n”,devProp.regsPerBlock);
printf(“扭曲大小:%d\n”,devProp.warpSize);
printf(“最大内存间距:%u\n”,devProp.memPitch);
printf(“每个块的最大线程数:%d\n”,devProp.maxThreadsPerBlock);
对于(int i=0;i<3;++i)
printf(“块的最大尺寸%d:%d\n”,i,devProp.maxThreadsDim[i]);
对于(int i=0;i<3;++i)
printf(“网格的最大维度%d:%d\n”,i,devProp.maxGridSize[i]);
printf(“时钟速率:%d\n”,devProp.clockRate);
printf(“总常量内存:%u\n”,devProp.totalConstMem);
printf(“纹理对齐:%u\n”,devProp.textureAlignment);
printf(“并发复制和执行:%s\n”,(devProp.deviceOverlap?“是”:“否”);
printf(“多处理器的数量:%d\n”,devProp.multiProcessorCount);
printf(“内核执行超时:%s\n”,(devProp.kernelExecTimeoutEnabled?“是”:“否”);
返回;
}
int main()
{
//CUDA设备的数量
国际发展账户;
cudaGetDeviceCount(&devCount);
printf(“CUDA设备查询…\n”);
printf(“有%d个CUDA设备。\n”,devCount);
//遍历设备
对于(int i=0;i
我的查询与for循环有关,就在main()结束之前,我逐个设置了每个设备,然后使用cudaResetDevice命令。我有一种奇怪的感觉,这段代码虽然没有产生任何错误,但我无法重置所有设备。相反,程序每次只重置默认设备,即设备0。有谁能告诉我,我应该如何重置4台设备中的每一台


感谢

cudaDeviceReset
用于在运行过程中销毁与给定GPU上下文关联的资源。一个CUDA进程无法重置或影响另一进程的上下文。因此,当您修改的设备查询调用
cudaDeviceReset
时,它只释放它分配的资源,而不释放任何其他进程正在使用的资源。

看起来您可以向GPU程序添加一个函数,以捕获ctrl+c信号(SIGINT),并为程序使用的每个设备调用cudaDeviceReset()函数

捕获SIGINT时调用函数的示例代码可在此处找到:

在您编写的每个GPU程序中都包含这样的代码似乎是一种很好的做法,我也会这样做:-)


我没有时间写一个完整详细的答案,所以请阅读另一个答案及其注释。

这可能太晚了,但如果您编写一个信号处理函数,您可以消除内存泄漏,并以可靠的方式重置设备:

// State variables for 
extern int no_sigint;
int no_sigint = 1;
extern int interrupts;
int interrupts = 0;

/* Catches signal interrupts from Ctrl+c.
   If 1 signal is detected the simulation finishes the current frame and
   exits in a clean state. If Ctrl+c is pressed again it terminates the
   application without completing writes to files or calculations but
   deallocates all memory anyway. */
void
sigint_handler (int sig)
{
  if (sig == SIGINT)
    {
      interrupts += 1;
      std::cout << std::endl
                << "Aborting loop.. finishing frame."
                << std::endl;

      no_sigint = 0;

      if (interrupts >= 2)
        {
          std::cerr << std::endl
                    << "Multiple Interrupts issued: "
                    << "Clearing memory and Forcing immediate shutdown!"
                    << std::endl;

          // write a function to free dynamycally allocated memory
          free_mem ();

          int devCount;
          cudaGetDeviceCount (&devCount);

          for (int i = 0; i < devCount; ++i)
            {
              cudaSetDevice (i);
              cudaDeviceReset ();
            }
          exit (9);
        }
    }
}
//的状态变量
外部内部无信号;
int no_sigint=1;
外部中断;
int中断=0;
/*捕捉来自Ctrl+c的信号中断。
如果检测到1个信号,模拟将完成当前帧并
以干净的状态退出。如果再次按下Ctrl+c,则会终止
应用程序未完成文件写入或计算,但
还是释放所有内存*/
无效的
信号处理器(信号处理器)
{
if(sig==SIGINT)
{
中断+=1;

std::cout感谢您的及时回复。那么我应该如何逐个重置每个设备。为了获得devcount,我必须调用cudaGetDeviceCount。这会在默认设备0中启动上下文吗?您能建议一种方法来确保每个gpu设备的gpu内存清除吗?谢谢CUDA 4.0,您需要调用cudaS在执行任何其他操作之前先重置设备。但我重复一下,cudaDeviceReset只重置执行的程序所执行的操作。如果GPU处于“坏”状态由于另一个进程所做的状态,它不能重置或以其他方式影响该状态。在驱动程序中实现了对上下文的基本保护,它明确地防止了这一点。因此,如果我必须使用CTRL C在中间终止内核,那么如果我使用上面提到的程序,目的是清除。资源,那么你的意思是说这将是徒劳的,并且由于突然终止而可能没有被擦除的全局设备内存将不会被清理?那么,你能为这个问题提出一个解决方案吗?因为可以肯定的是,我将在开发阶段使用ctrl-C故意终止我的内核我只能把重启机器看作是一种解决办法,尽管如此,还是很烦人的。另外,非常感谢您的及时回复。
int main(){ 
.....
for (int simulation_step=1 ; simulation_step < SIM_STEPS && no_sigint; ++simulation_step)
{
   .... simulation code
}
free_mem();
... cuda device resets
return 0;
}