У меня есть цикл, в котором я запускаю несколько ядер на графический процессор. Ниже приведен фрагмент кода:Использование нескольких графических процессоров OpenCL
for (int idx = start; idx <= end ;idx ++) {
ret = clEnqueueNDRangeKernel(command_queue, memset_kernel, 1, NULL,
&global_item_size_memset, &local_item_size, 0, NULL, NULL);
ASSERT_CL(ret, "Error after launching 1st memset_kernel !");
ret = clEnqueueNDRangeKernel(command_queue, cholesky_kernel, 1, NULL,
&global_item_size_cholesky, &local_item_size, 0, NULL, NULL);
ASSERT_CL(ret, "Error after launching 1st cholesky_kernel !");
ret = clEnqueueNDRangeKernel(command_queue, ckf_kernel1, 1, NULL,
&global_item_size_kernel1, &local_item_size, 0, NULL, NULL);
ASSERT_CL(ret, "Error after launching ckf_kernel1[i] !");
clFinish(command_queue);
ret = clEnqueueNDRangeKernel(command_queue, memset_kernel, 1, NULL,
&global_item_size_memset, &local_item_size, 0, NULL, NULL);
ASSERT_CL(ret, "Error after launching 2nd memset_kernel !");
ret = clEnqueueNDRangeKernel(command_queue, cholesky_kernel, 1, NULL,
&global_item_size_cholesky, &local_item_size, 0, NULL, NULL);
ASSERT_CL(ret, "Error after launching 2nd cholesky_kernel !");
ret = clSetKernelArg(ckf_kernel2, 4, sizeof(idx), (void *)&idx);
ret = clEnqueueNDRangeKernel(command_queue, ckf_kernel2, 1, NULL,
&global_item_size_kernel2, &local_item_size, 0, NULL, NULL);
ASSERT_CL(ret, "Error after launching ckf_kernel2 !");
Теперь я хотел использовать этот код для системы, которая имеет несколько графических процессоров. Поэтому я выполнил следующие шаги:
- создал единый контекст для всех графических процессоров.
- создал одну командную очередь для каждого устройства.
- созданы отдельные ядра для каждого устройства (фрагмент кода ниже при условии двух GPU)
выделены отдельные буферы устройств для каждого устройства
cl_kernel ckf_kernel1[2]; cl_kernel ckf_kernel2[2]; cl_kernel cholesky_kernel[2]; cl_kernel memset_kernel[2]; // read get kernel. ckf_kernel1[0] = clCreateKernel(program, "ckf_kernel1", &ret); ASSERT_CL(ret, "Cannot load ckf_kernel1[i]!"); ckf_kernel2[0] = clCreateKernel(program, "ckf_kernel2", &ret); ASSERT_CL(ret, "Cannot load ckf_kernel2!"); memset_kernel[0] = clCreateKernel(program, "memset_zero", &ret); ASSERT_CL(ret, "Cannot load memset_kernel!"); cholesky_kernel[0] = clCreateKernel(program, "cholesky_kernel", &ret); ASSERT_CL(ret, "Cannot load cholesky_kernel!"); ckf_kernel1[1] = clCreateKernel(program, "ckf_kernel1", &ret); ASSERT_CL(ret, "Cannot load ckf_kernel1[i]!"); ckf_kernel2[1] = clCreateKernel(program, "ckf_kernel2", &ret); ASSERT_CL(ret, "Cannot load ckf_kernel2!"); memset_kernel[1] = clCreateKernel(program, "memset_zero", &ret); ASSERT_CL(ret, "Cannot load memset_kernel!"); cholesky_kernel[1] = clCreateKernel(program, "cholesky_kernel", &ret); ASSERT_CL(ret, "Cannot load cholesky_kernel!");
Теперь, я не знаю, как запустить ядра на различные устройства внутри цикла. Как заставить их выполнять параллельно? Обратите внимание, что в этом цикле есть команда clFinish.
Другой вопрос: стандартная практика заключается в использовании нескольких потоков/процессов на хосте, где каждый поток/процесс отвечает за запуск ядер на одном графическом процессоре?
Вы перекрываете связь с вычислениями или совместно используете одно и то же общее? –
Можете ли вы немного уточнить, я не уверен в вашем вопросе. – user1274878
«Стандартная практика заключается в использовании нескольких потоков/процессов на хосте, где каждый thread/process отвечает за запуск ядер на одном GPU? »- не типично. – Dithermaster