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 }