Вызов библиотеки с поддержкой CUDA в новом потоке - PullRequest
2 голосов
/ 15 июля 2011

У меня есть некоторый код, который я написал и поместил в свою собственную библиотеку, которая использует CUDA для некоторой обработки на GPU.

Я создаю интерфейс GUI с использованием Qt, и как часть загрузки GUI я вызываю

CUresult res;
CUdevice dev;
CUcontext ctx;

    cuInit(0);
    cuDeviceGet(dev,0);
    cuCtxCreate(ctx, 0, dev);

для инициализации графического процессора, чтобы приложение максимально быстро реагировало при вызове библиотеки с поддержкой CUDA.

Проблема в том, что я начал пытаться вызвать мою библиотеку с поддержкой CUDA из другого потока.

Должен ли я приложить какие-то усилия, чтобы сделать это? Этот другой поток является единственным, вызывающим любые функции cuda (за исключением основного потока, вызывающего cuInit ()), но мой код падает на вызов cudaFree () в моей библиотеке cuda. ​​

Спасибо

Ответы [ 3 ]

3 голосов
/ 15 июля 2011

Контексты связаны с потоком, который их создал.Таким образом, вы можете выбрать «рабочий поток» графического процессора для установки контекста или использовать вызовы миграции контекста API драйвера ( cuCtxPopCurrent и cuCtxPushCurrent ) для перемещения контекста из потока внить.Имейте в виду, что миграция контекста не является бесплатной, поэтому, если вы собираетесь делать это много, вы заметите увеличение задержки GPU.

1 голос
/ 20 июля 2011

Решением, которое я использовал в прошлом (Cuda 2.2), является также парадигма «рабочий поток» графического процессора, где один выделенный поток управляет контекстом CUDA.

Очень общий подход (использующий boost:: связать с переадресацией вызовов функций) можно увидеть на http://forums.nvidia.com/index.php?showtopic=66598

Пример кода по ссылке:

GPUWorker gpu0(0);
GPUWorker gpu1(1);

// allocate data
int *d_data0;
gpu0.call(bind(cudaMalloc, (void**)((void*)&d_data0), sizeof(int)*N));
int *d_data1;
gpu1.call(bind(cudaMalloc, (void**)((void*)&d_data1), sizeof(int)*N));

// call kernel
gpu0.callAsync(bind(kernel_caller, d_data0, N));
gpu1.callAsync(bind(kernel_caller, d_data1, N));

Объект GPUWorker принимает объекты функций через метод вызова, которые помещаются наочередь.GPUWorker :: run () затем выскочит из функциональных объектов и вызовет их в соответствующем контексте CUDA.

1 голос
/ 16 июля 2011

Обычно я не использую API драйвера, поэтому не могу дать прямой совет, кроме как легко запутаться между cuCtxPopCurrent() и cuCtxPushCurrent().

Но обязательно ознакомьтесь с CUDA Toolkit 4.0 Readiness Tech Brief . CUDA 4.0 внесла некоторые значительные изменения в работу многопоточных и многопользовательских графических процессоров, их стоит прочитать.

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