複数のデバイスで実行されるopenCLテストの作成方法に関する質問があります 式を計算するopenCLプログラムを作成したいとします。B + C D、これは私が 複数のデバイスで実行されるopenCLテストの作成方法
- を考えると、他のものです並行して3つのタスクを実行するホストコードと、異なるデバイスで実行する各タスクシングルタスクのために特定のデバイスを割り当てることが
私は はあなた
複数のデバイスで実行されるopenCLテストの作成方法に関する質問があります 式を計算するopenCLプログラムを作成したいとします。B + C D、これは私が 複数のデバイスで実行されるopenCLテストの作成方法
私は はあなた
OpenCLのは、考慮されるすべてのものに、かなり明確なAPIをありがとう助けてください。コンテキストの作成時に特定のデバイスを指定するように要求され、キューを作成するときに特定のコンテキストを指定するように要求されます。だから、ほとんどの文字通りの用語で、あなたのタスクを達成することは
//This is going to be pseudocode; I'm not going to look up the literal syntax for this stuff
//It is going to closely resemble how you'd write this code in C++, though
std::vector<_type> perform_tasks(cl_device_id ab_device, cl_device_id cd_device, cl_device_id n_m_device) {
cl_context ab_context = clCreateContext(ab_device);
cl_context cd_context = clCreateContext(cd_device);
cl_context n_m_context = clCreateContext(n_m_device);
cl_command_queue ab_queue = clCreateQueue(ab_context, ab_device);
cl_command_queue cd_queue = clCreateQueue(cd_context, cd_device);
cl_command_queue n_m_queue = clCreateQueue(n_m_context, n_m_device);
cl_kernel ab_kernel = get_ab_kernel(ab_context, ab_device);
cl_kernel cd_kernel = get_ab_kernel(cd_context, cd_device);
cl_kernel n_m_kernel = get_ab_kernel(n_m_context, n_m_device);
set_args_for_ab(ab_kernel);
set_args_for_cd(cd_kernel);
set_args_for_n_m(n_m_kernel);
cl_event events[2];
clEnqueueKernel(ab_queue, ab_kernel, &events[0]);
clEnqueueKernel(cd_queue, cd_kernel, &events[1]);
//Here, I'm assuming that the n_m kernel depends on the results of ab and cd, and thus
//must be sequenced afterwards.
clWaitForEvents(2, events);
copy_ab_and_cd_data_into_n_m_buffers();
cl_event n_m_event;
clEnqueueKernel(n_m_queue, n_m_kernel, &n_m_event);
clWaitForEvents(1, &n_m_event);
return copy_n_m_data_to_host();
}
のと同じくらい簡単です。しかし、あなたの質問によって不用意行っているようです対処する必要が大きな疑問、あります:なぜ?
このようなロジックから、次のようなものを書くのではなく、どんな種類の性能向上が期待されますか?あなたが提案しているプログラムロジックの一種で
kernel void ab_cd(global _type * a, global _type * b, global _type * c, global _type * d, global _type * output) {
long id = get_global_id(0);
output[id] = a[id] * b[id] + c[id] * d[id];
}
、あなたは単純に(私が説明した擬似コードでcopy_ab_and_cd_data_into_n_m_buffers()
内部で発生するであろう)異なるデバイス間でデータを転送しようとするから避けられないオーバーヘッドが発生するつもりです。あなたはこのようなプログラムのために複数のデバイスを使用することを約束している場合、それはまだ簡単です。このような何か書くこと(そしておそらくよりパフォーマンス!):あなたはFPGAで作業し、またはを扱っている場合を除き
//Again; using pseudocode. Again, gonna look like C++ code.
cl_event perform_tasks(cl_device_id device, cl_context * context, cl_command_queue * queue, cl_kernel * kernel) {
*context = clCreateContext(device);
*queue = clCreateQueue(context, device);
*kernel = get_kernel();
cl_event event;
clEnqueueKernel(queue, kernel, &event);
return event;
}
int main() {
std::vector<cl_device_id> device_ids = get_device_ids();
std::vector<_type> results;
std::vector<cl_context> contexts(device_ids.size());
std::vector<cl_command_queue> queues(device_ids.size());
std::vector<cl_kernel> kernels(device_ids.size());
std::vector<cl_event> events;
for(size_t i = 0; i < device_ids.size(); i++) {
events.emplace_back(perform_tasks(device_ids[i], &contexts[i], &queues[i], &kernels[i]));
}
clWaitForEvents(events.size(), events.data());
for(cl_command_queue const& queue : queues) {
std::vector<_type> result = read_results_from_queue(queue);
results.insert(results.end(), result.begin(), result.end());
}
//results now contains the results of all executions
return 0;
}
を特にエキゾチックな作業負荷では、異なるデバイスで異なる作業を行うことが絶対に必要ですが、必要以上に自分のために多くの作業を作成するだけです。
Xiremaありがとう、私は複数のFPGAデバイス上で実行されるopenCLテストに取り組んでいますので、本当に頭がおかしくなります – tpham1002002
@ tpham1002002待って、実際には* FPGAの扱いですか?ハァッ。まあ、私が言及したように、私が提供した最初のコードは、そのモデルを扱うでしょう。私の元々の主張がそのまま適用されますが、複数のデバイス間で1つの計算を分割することは理にかなっています。特に計算のサブコンポーネントがデバイス間で類似している場合は特にそうです。 – Xirema
どこで止めましたか?プラットフォームとデバイスを選択してキューを選択しましたが、これらのデバイスにタスクを割り当てることができませんでしたか? –
openclのどのバージョン?どのようなデバイスですか?どのような仕事の配布ですか? –