cudaDeviceReset для нескольких графических процессоров - PullRequest
8 голосов
/ 22 августа 2011

В настоящее время я работаю на сервере GPU, на котором установлено 4 процессора Tesla T10. Пока я продолжаю тестировать ядра и вынужден часто убивать процессы с помощью 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;
}

Мой запрос связан с циклом for непосредственно перед завершением main (), в котором я устанавливаю каждое устройство по одному, а затем использую команду cudaResetDevice. У меня странное ощущение, что этот код, хотя и не выдает никаких ошибок, но я не могу сбросить все устройства. Вместо этого программа сбрасывает только устройство по умолчанию, т.е. устройство 0 каждый раз. Может кто-нибудь сказать мне, что я должен сделать, чтобы сбросить каждое из 4 устройств.

Спасибо

Ответы [ 3 ]

5 голосов
/ 24 июня 2012

Похоже, что вы можете добавить функцию в свои программы GPU для перехвата сигнала ctrl + c (SIGINT) и вызвать функцию cudaDeviceReset () для каждого устройства, которое использовалось программой.код для вызова функции при перехвате SIGINT можно найти здесь:

https://stackoverflow.com/a/482725

Хорошей практикой является включение такого кода в каждую написанную вами программу для графического процессора, и ясделайте то же самое: -)

У меня нет времени, чтобы написать полный подробный ответ, поэтому прочитайте другой ответ и его комментарии.

3 голосов
/ 31 мая 2013

Возможно, это слишком поздно, но если вы напишите функцию обработки сигналов, вы сможете избавиться от утечек памяти и выполнить перезагрузку устройства определенным образом:

// 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 main(){ 
.....
for (int simulation_step=1 ; simulation_step < SIM_STEPS && no_sigint; ++simulation_step)
{
   .... simulation code
}
free_mem();
... cuda device resets
return 0;
}

Если вы используете этот код (вы даже можете включить первый фрагмент во внешний заголовок, он работает. У вас может быть 2 уровня управления ctrl + c: первое нажатие останавливает симуляцию и завершается нормально, ноПриложение завершает рендеринг шага, который отлично подходит для корректной остановки и получения правильных результатов. Если вы снова нажмете Ctrl + C, приложение закроется, освободив всю память.

1 голос
/ 22 августа 2011

cudaDeviceReset предназначен для уничтожения ресурсов, связанных с данным контекстом графического процессора, в процессе, в котором он запущен.Один процесс CUDA не может сбросить или иным образом повлиять на контекст другого процесса.Поэтому, когда ваш модифицированный запрос устройства вызывает cudaDeviceReset, он освобождает только выделенные ресурсы, а не ресурсы, используемые каким-либо другим процессом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...