Есть ли какая-то несовместимость с Boost :: thread () и Nvidia CUDA? - PullRequest
1 голос
/ 23 мая 2011

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

В настоящее время я вызываю ядра cuda в оболочке статической функции C ++, поэтому я могу вызывать ядра из файла .cpp (не .cu), например:

//kernels.cu:

//kernel definition
__global__ void kernelCall_kernel(  dataRow* in,  dataRow* out,  void* additionalData){
    //Do something
};

//kernel handler, so I can compile this .cu and link it with the main project and call it within a .cpp file
extern "C" void kernelCall( dataRow* in,  dataRow* out,  void* additionalData){ 
    int blocksize = 256;  
    dim3 dimBlock(blocksize);
    dim3 dimGrid(ceil(tableSize/(float)blocksize)); 
    kernelCall_kernel<<<dimGrid,dimBlock>>>(in, out, additionalData);   

}

Если я вызываю обработчик как обычную функцию, напечатанные данные верны.

//streamProcessing.cpp
//allocations and definitions of data omitted

//copy data to GPU
cudaMemcpy(data_d,data_h,tableSize,cudaMemcpyHostToDevice);
//call:
kernelCall(data_d,result_d,null);
//copy data back
cudaMemcpy(result_h,result_d,resultSize,cudaMemcpyDeviceToHost);
//show result:
printTable(result_h,resultSize);// this just iterate and shows the data

Но чтобы разрешить параллельное копирование и выполнение данных на GPU, мне нужно создать поток, поэтому, когда я вызываю его, создаю новый boost :: thread:

//allocations, definitions of data,copy data to GPU omitted
//call:
boost::thread* kernelThreadOwner = new boost::thread(kernelCall, data_d,result_d,null); 
kernelThreadOwner->join();
//Copy data back and print ommited

Я просто получаю мусор при печати результата в конце.

В настоящее время я использую только один поток для целей тестирования, поэтому не должно быть большой разницы в его непосредственном вызове или создании потока. Я понятия не имею, почему вызов функции напрямую дает правильный результат, а при создании потока - нет. Это проблема с CUDA и Boost? Я что-то пропустил? Спасибо за совет.

1 Ответ

4 голосов
/ 24 мая 2011

Проблема в том, что (до CUDA 4.0) контексты CUDA связаны с потоком, в котором они были созданы. Когда вы используете два потока, у вас есть два контекста. Контекст, который основной поток выделяет и читает, и контекст, в котором поток, в котором выполняется ядро, не совпадают. Распределение памяти не переносимо между контекстами. Они фактически разделяют области памяти внутри одного и того же графического процессора.

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

...