DPCT1113
目次
DPCT1113#
メッセージ#
<function name> が多次元カーネルで呼び出される場合、sycl::nd_item::barrier(sycl::access::fence_space::local_space)
を sycl::nd_item::barrier()
に置き換えることを検討してください。
詳細な説明#
work-group 内の各ワーク項目間でグローバル・デバイス・メモリーへの重複するアクセスがない場合、__syncthreads()
API は、sycl::nd_item::barrier(sycl::access::fence_space::local_space)
に移行可能なカーネル実行の 1D インデックス空間を使用してカーネルを呼び出します。2D/3D インデックス空間を使用してカーネルを呼び出す場合、work-group 内の各ワーク項目からグローバルメモリーへのアクセスが重複する可能性があり、バリアを超えたワーク項目間でデータの依存関係が生じる可能性があります。この場合、sycl::nd_item::barrier()
呼び出しを sycl::access::fence_space::global_and_local
に置き換える必要があります。
修正方法の提案
例えば、以下のオリジナル CUDA* コードについて考えてみます。
1 __global__ void kernel(float *mem) {
2 unsigned int tid = threadIdx.x + blockDim.x * blockIdx.x;
3 ...
4 mem[tid] = ...;
5 __syncthreads();
6 ...
7 ... = mem[tid];
8}
9
10 void foo(float *mem) {
11 kernel<<<16, 16>>>(mem); //1D index space of a SYCL kernel execution
12 }
このコードは、以下の SYCL* コードに移行されます。
1 void kernel(float *mem, const sycl::nd_item<3> &item_ct1) {
2 unsigned int tid = item_ct1.get_local_id(2) +
3 item_ct1.get_local_range(2) * item_ct1.get_group(2);
4 ...
5 mem[tid] = ...; // global memory access without overlap among each work-item in a work-group
6 /*
7 DPCT1113:0: Consider replacing
8 sycl::nd_item::barrier(sycl::access::fence_space::local_space) with
9 sycl::nd_item::barrier() if function "kernel" is called in a multidimensional
10 kernel.
11 */
12 item_ct1.barrier(sycl::access::fence_space::local_space);
13 ...
14 ... = mem[tid]; // global memory access without overlap among each work-item in a work-group
15 }
16
17 void foo(float *mem) {
18 dpct::get_default_queue().parallel_for(
19 sycl::nd_range<3>(sycl::range<3>(1, 1, 16) * sycl::range<3>(1, 1, 16),
20 sycl::range<3>(1, 1, 16)),
21 [=](sycl::nd_item<3> item_ct1) {
22 kernel(mem, item_ct1);
23 });
24 }
移行後、移行された SYCL* カーネルコードを 2D カーネルに更新します。
1 void kernel(float *mem, const sycl::nd_item<3> &item_ct1) {
2 unsigned int tidx = item_ct1.get_local_id(2) +
3 item_ct1.get_local_range(2) * item_ct1.get_group(2);
4 unsigned int tidy = item_ct1.get_local_id(1) +
5 item_ct1.get_local_range(1) * item_ct1.get_group(1);
6
7 ...
8 mem[tidx] = ...; // global memory access with overlap among each work-item in a work-group
9 mem[tidy] = ...; // global memory access with overlap among each work-item in a work-group
10 /*
11 DPCT1113:0: Consider replacing
12 sycl::nd_item::barrier(sycl::access::fence_space::local_space) with
13 sycl::nd_item::barrier() if function "kernel" is called in a multidimensional
14 kernel.
15 */
16 item_ct1.barrier(sycl::access::fence_space::local_space);
17 ...
18 ... = mem[tidx]; // global memory access with overlap among each work-item in a work-group
19 ... = mem[tidy]; // global memory access with overlap among each work-item in a work-group
20 }
21
22 void foo(float *mem) {
23 dpct::get_default_queue().parallel_for(
24 sycl::nd_range<3>(sycl::range<3>(1, 4, 4) * sycl::range<3>(1, 4, 4),
25 sycl::range<3>(1, 4, 4)), /*2D index space of a SYCL kernel execution */
26
27 [=](sycl::nd_item<3> item_ct1) {
28 kernel(mem, item_ct1);
29 });
30 }
このコードは次のように書き換えられます。
1 void kernel(float *mem, const sycl::nd_item<3> &item_ct1) {
2 unsigned int tidx = item_ct1.get_local_id(2) +
3 item_ct1.get_local_range(2) * item_ct1.get_group(2);
4 unsigned int tidy = item_ct1.get_local_id(1) +
5 item_ct1.get_local_range(1) * item_ct1.get_group(1);
6
7 ...
8 mem[tidx] = ...; // global memory access with overlap among each work-item in a work-group
9 mem[tidy] = ...; // global memory access with overlap among each work-item in a work-group
10 item_ct1.barrier(sycl::access::fence_space::global_and_local);
11 ...
12 ... = mem[tidx]; // global memory access with overlap among each work-item in a work-group
13 ... = mem[tidy]; // global memory access with overlap among each work-item in a work-group
14 }
15
16 void foo(float *mem) {
17 dpct::get_default_queue().parallel_for(
18 sycl::nd_range<3>(sycl::range<3>(1, 4, 4) * sycl::range<3>(1, 4, 4),
19 sycl::range<3>(1, 4, 4)),
20 [=](sycl::nd_item<3> item_ct1) {
21 kernel(mem, item_ct1);
22 });
23 }