queue.wait() 和等待缓冲区析构有什么区别
What's the difference between queue.wait() and waiting on a buffer to destruct
考虑这个例子,我用 gpuQueue.wait():
等待完成
constexpr unsigned dataSize = 1024;
std::vector<float> in1 (dataSize, 0); std::iota(in1.begin(), in1.end(), 0 );
std::vector<float> in2 (dataSize, 0); std::iota(in2.begin(), in2.end(), 25);
std::vector<float> out (dataSize, 0);
float coeff1 = 4;
cl::sycl::buffer<float, 1> bufIn1(in1.data(), dataSize);
cl::sycl::buffer<float, 1> bufIn2(in2.data(), dataSize);
cl::sycl::buffer<float, 1> bufOut(out.data(), dataSize);
cl::sycl::queue gpuQueue{cl::sycl::gpu_selector()};
gpuQueue.submit([&](cl::sycl::handler &cgh) {
auto in1 = bufIn1.get_access<cl::sycl::access::mode::read> (cgh);
auto in2 = bufIn2.get_access<cl::sycl::access::mode::read> (cgh);
auto temp = bufOut.get_access<cl::sycl::access::mode::write>(cgh);
auto kernel = [=](cl::sycl::id<1> id) {
temp[id] = in1[id] * in2[id] + coeff1;
};
cgh.parallel_for<floatIteration>(cl::sycl::range<1>(dataSize), kernel);
});
gpuQueue.wait();
for( unsigned i = 0; i < dataSize; ++i )
std::cout << out[i] << " " << (in1[i] * in2[i] + coeff1) << "\n";
这个例子中缓冲区在嵌套范围内并且没有等待:
constexpr unsigned dataSize = 1024;
std::vector<float> in1 (dataSize, 0); std::iota(in1.begin(), in1.end(), 0 );
std::vector<float> in2 (dataSize, 0); std::iota(in2.begin(), in2.end(), 25);
std::vector<float> out (dataSize, 0);
float coeff1 = 4;
{
cl::sycl::buffer<float, 1> bufIn1(in1.data(), dataSize);
cl::sycl::buffer<float, 1> bufIn2(in2.data(), dataSize);
cl::sycl::buffer<float, 1> bufOut(out.data(), dataSize);
cl::sycl::queue gpuQueue{cl::sycl::gpu_selector()};
gpuQueue.submit([&](cl::sycl::handler &cgh) {
auto in1 = bufIn1.get_access<cl::sycl::access::mode::read>(cgh);
auto in2 = bufIn2.get_access<cl::sycl::access::mode::read>(cgh);
auto temp = bufOut.get_access<cl::sycl::access::mode::write>(cgh);
auto kernel = [=](cl::sycl::id<1> id) {
temp[id] = in1[id] * in2[id] + coeff1;
};
cgh.parallel_for<floatIteration>(cl::sycl::range<1>(dataSize), kernel);
});
}
for( unsigned i = 0; i < dataSize; ++i )
std::cout << out[i] << " " << (in1[i] * in2[i] + coeff1) << "\n";
两者的输出是:
queue.wait()
nested scope
0 4
4 4
0 30
30 30
0 58
58 58
为什么 queue.wait() 不等待将缓冲区中的数据复制回主机?
queue.wait()
等待所有队列操作完成,在本例中,与floatIteration
内核一起执行命令组。
但是,您真正需要的是在主机端查看操作的 side-effects。在 SYCL 中,当您通过缓冲区对象写入时,您不一定使用与输入相同的主机内存(例如 in1.data(
))。只有当缓冲区范围结束时,或者当有一个命令组要求对主机的副作用可见时(例如,显式复制回主机),才保证在主机中更新数据。
第二个代码是正确的,你只在拷贝完成后读取主机中的数据。第一个在等待正确之前需要显式复制操作。
考虑这个例子,我用 gpuQueue.wait():
等待完成 constexpr unsigned dataSize = 1024;
std::vector<float> in1 (dataSize, 0); std::iota(in1.begin(), in1.end(), 0 );
std::vector<float> in2 (dataSize, 0); std::iota(in2.begin(), in2.end(), 25);
std::vector<float> out (dataSize, 0);
float coeff1 = 4;
cl::sycl::buffer<float, 1> bufIn1(in1.data(), dataSize);
cl::sycl::buffer<float, 1> bufIn2(in2.data(), dataSize);
cl::sycl::buffer<float, 1> bufOut(out.data(), dataSize);
cl::sycl::queue gpuQueue{cl::sycl::gpu_selector()};
gpuQueue.submit([&](cl::sycl::handler &cgh) {
auto in1 = bufIn1.get_access<cl::sycl::access::mode::read> (cgh);
auto in2 = bufIn2.get_access<cl::sycl::access::mode::read> (cgh);
auto temp = bufOut.get_access<cl::sycl::access::mode::write>(cgh);
auto kernel = [=](cl::sycl::id<1> id) {
temp[id] = in1[id] * in2[id] + coeff1;
};
cgh.parallel_for<floatIteration>(cl::sycl::range<1>(dataSize), kernel);
});
gpuQueue.wait();
for( unsigned i = 0; i < dataSize; ++i )
std::cout << out[i] << " " << (in1[i] * in2[i] + coeff1) << "\n";
这个例子中缓冲区在嵌套范围内并且没有等待:
constexpr unsigned dataSize = 1024;
std::vector<float> in1 (dataSize, 0); std::iota(in1.begin(), in1.end(), 0 );
std::vector<float> in2 (dataSize, 0); std::iota(in2.begin(), in2.end(), 25);
std::vector<float> out (dataSize, 0);
float coeff1 = 4;
{
cl::sycl::buffer<float, 1> bufIn1(in1.data(), dataSize);
cl::sycl::buffer<float, 1> bufIn2(in2.data(), dataSize);
cl::sycl::buffer<float, 1> bufOut(out.data(), dataSize);
cl::sycl::queue gpuQueue{cl::sycl::gpu_selector()};
gpuQueue.submit([&](cl::sycl::handler &cgh) {
auto in1 = bufIn1.get_access<cl::sycl::access::mode::read>(cgh);
auto in2 = bufIn2.get_access<cl::sycl::access::mode::read>(cgh);
auto temp = bufOut.get_access<cl::sycl::access::mode::write>(cgh);
auto kernel = [=](cl::sycl::id<1> id) {
temp[id] = in1[id] * in2[id] + coeff1;
};
cgh.parallel_for<floatIteration>(cl::sycl::range<1>(dataSize), kernel);
});
}
for( unsigned i = 0; i < dataSize; ++i )
std::cout << out[i] << " " << (in1[i] * in2[i] + coeff1) << "\n";
两者的输出是:
queue.wait() | nested scope |
---|---|
0 4 | 4 4 |
0 30 | 30 30 |
0 58 | 58 58 |
为什么 queue.wait() 不等待将缓冲区中的数据复制回主机?
queue.wait()
等待所有队列操作完成,在本例中,与floatIteration
内核一起执行命令组。
但是,您真正需要的是在主机端查看操作的 side-effects。在 SYCL 中,当您通过缓冲区对象写入时,您不一定使用与输入相同的主机内存(例如 in1.data(
))。只有当缓冲区范围结束时,或者当有一个命令组要求对主机的副作用可见时(例如,显式复制回主机),才保证在主机中更新数据。
第二个代码是正确的,你只在拷贝完成后读取主机中的数据。第一个在等待正确之前需要显式复制操作。