Как запустить CPU и GPU одновременно, используя потоки? - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть две функции, которые я хочу запустить с использованием потоков.

1) Функция ЦП, к которой я могу присоединиться к потоку, используя:

thread t1(vector_add, p->iNum1, p->iNum2, p->iNumAns, p->flag);
t1.join();

2) и ядро ​​графического процессора

vectorAdd_gpu <<<blocksPerGrid, threadsPerBlock >>>(s.a1, s.a2, s.a2, s.flag);

Но моя проблема заключается в том, как вызвать вызов Kernel GPU, используя потоки, и присоединить его, чтобы он мог работать одновременно с функцией ЦП.

vectorAdd_gpu <<<blocksPerGrid, threadsPerBlock >>>(s.a1, s.a2, s.a2, s.flag);

thread t2(vectorAdd_gpu);
t2.join();

Любой другойспособ запустить процессор и функцию графического процессора одновременно с использованием потоков?

1 Ответ

0 голосов
/ 09 декабря 2018

Как сказали talonmies,

Поместите свой вызов в лямбда-функцию

auto myFunc = [&](){
    cudaStream_t stream2;
    cudaSetDevice(device2); 
    cudaStreamCreate (&stream2);
    vectorAdd_gpu <<<blocksPerGrid, threadsPerBlock,0,stream2 >>>(s.a1, s.a2, s.a2, s.flag);
    cudaStreamSynchronize(stream2);
    cudaStreamDestroy(stream2);
};

, затем передайте его в поток.

thread t2(myFunc);
t2.join();

Но вместо этого вывсе еще может использовать тот же основной поток вашего приложения с потоками асинхронно при работе процессора.Я только что показал то, что ты хотел увидеть.Использование одного и того же потока асинхронно может быть более эффективным, чем повторное создание потоков и повторное объединение потоков, в зависимости от объема работы.Возможно, повторное присоединение требует больше времени, чем синхронизация и запуск ядра здесь.Сколько вызовов ядра вы делаете в секунду?

В следующем блоге от Nvidia, https://devblogs.nvidia.com/how-overlap-data-transfers-cuda-cc/ есть хороший пример однопоточной асинхронной CUDA:

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  cudaMemcpyAsync(&d_a[offset], &a[offset], 
                  streamBytes, cudaMemcpyHostToDevice, cudaMemcpyHostToDevice, stream[i]);
}

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  kernel<<<streamSize/blockSize, blockSize, 0, stream[i]>>>(d_a, offset);
}

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  cudaMemcpyAsync(&a[offset], &d_a[offset], 
                  streamBytes, cudaMemcpyDeviceToHost, cudaMemcpyDeviceToHost, stream[i]);
}

это только один из способов перекрытия асинхронных потоков.

...