2014-01-31 6 views
-1

У меня есть код C++, который вызывает код CUDA. Я использую GTX 680 GPU. В настоящее время он работает так:Запуск параллельных ядер CUDA, вызванных из функций оболочки C++

fn_1(); //calls CUDA code (indirectly) 
fn_a(); //calls CUDA code (indirectly), must run AFTER fn_1 
fn_2(); //calls CUDA code (indirectly), must run AFTER fn_1 
fn_b(); //calls CUDA code (indirectly), must run AFTER fn_2 
fn_3(); //calls CUDA code (indirectly), must run AFTER fn_2 
fn_c(); //calls CUDA code (indirectly), must run AFTER fn_3 

и каждая функция, как это:

void fn_*(){ 
    call_cuda_fn_x(); //calls CUDA code 
    call_cuda_fn_y(); //calls CUDA code, must run AFTER call_cuda_fn_x 
} 

Некоторые из этих функций не в полной мере использовать свой GPU (GTX 680). Поэтому я хотел бы, чтобы fn_2() и fn_a() выполнялись одновременно, а затем вызываем fn_3() и fn_b(), как только fn_2() заканчивается. Затем синхронизируйте все после вызова fn_c().

fn_1(); 
fn_2(); also launch fn_a() 
fn_3(); also launch fn_b() 
fn_c(); 
synchronise() //ensure that fn_a() && fn_b() && fn_c() have finished. 

Могу ли я это сделать? Если да, можете ли вы набросать, как?

(Обратите внимание, что, например, fn_b() имеет внутри него несколько функций C++, которые должны запускаться последовательно - по-видимому, это означает, что мне нужно использовать более одного потока cpu, чтобы одновременно вызвать fn_2() и fn_a() ? - то есть я не могу полагаться только называя все мои CUDA ядра и только синхронизироваться в самом конце)

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

C++ функция call_cuda_fn_x() имеет вид, например:

void call_cuda_fn_x(){ 
    .... //some c++ working 
    convolve<<<n_blocks, n_threads, n_floats*sizeof(float)>>> 
     (mat1, mat2, ..); 
    CUDA_CHECK_RETURN(cudaThreadSynchronize()); //Wait for the GPU work to finish, BEFORE calling the next CUDA code. 

    mat_mul<<<n_blocks, n_threads, n_floats*sizeof(float)>>> 
     (mat1, mat2, ..); 
    CUDA_CHECK_RETURN(cudaThreadSynchronize()); //Wait for the GPU work to finish. 
    .... //some more c++ working 
} 

Обратите внимание на необходимость вызова функции cudaThreadSynchronize() в этой функции C++.

+0

Читали [требования] (http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#conurrent-kernel-execution) для одновременного выполнения ядра, или изучил [примерный пример кода ядра] (http://docs.nvidia.com/cuda/cuda-samples/index.html#concurrent-kernels)? –

+0

Роберт - спасибо. Очень полезно. Так что GTX680 может запускать параллельные ядра - хорошо. И, как я понимаю, в случаях, когда мои функции C++ не зависят от результатов кода CUDA (т.е. нет «if (cuda_answer> 0.0) {...}»), я могу одновременно запускать несколько потоков, каждый из которых который последовательно запускает свой код, все вызываемые из одного потока cpu - тоже хорошие. Где код C++ зависит от результатов cuda, я все еще не уверен, что делать, но я сейчас на полпути :) Спасибо. – osbert

+0

Если хост-код зависит от результатов cuda, то вам (предположительно) нужно скопировать результаты cuda с устройства на хост. Выпустите устройство для размещения 'cudaMemcpyAsync' для этих результатов * в тот же поток *, где было запущено ядро, генерирующее эти результаты. Затем выпустите 'cudaStreamSynchronize' для этого потока, прежде чем использовать эти данные в главном коде. Одновременное выполнение ядра может быть проще достигнуть/наблюдать за linux вместо Windows (WDDM) по целому ряду причин. –

ответ

0

Звонки ядра асинхронны с точки зрения ЦП, поэтому, если вы вызываете два ядра подряд, второй будет вызываться, не дожидаясь завершения первого. Это означает, что элемент управления немедленно возвращается в CPU.

Таким образом, вы можете запускать в следующей последовательности.

fn_1() 
cudaEventSynchronize() 
fn_2() 
fn_a() 
cudaEventSynchronize() 
fn_b() 
fn_3() 
cudaEventSynchronize() 
fn_c() 
+0

Спасибо Itachi. Но внутри fn_2() у меня есть несколько вызовов cudaThreadSynchronize(). (Я должен иметь это, потому что ядро ​​вызывает внутри fn_2() должно быть последовательным). Разве это не означает, что мой C++-поток зависает при вызове cudaThreadSynchronize()? – osbert

+0

Ядро вызывает внутри fn_2()? Вы запускаете больше ядер из fn_2() с помощью Dynamaic Parallelsim? – Itachi

+0

fn_2() вызывает другие функции C++: call_cuda_fn_x(); и call_cuda_fn_y(); Они называют код CUDA, например.например: mat_mul <<< n_blocks, n_threads, n_floats * sizeof (float) >>> (arg1, arg2); CUDA_CHECK_RETURN (cudaThreadSynchronize()); \t - где mat_mul является \ _ \ _ global \ _ \ _ – osbert

Смежные вопросы