Intel® FPGA SDK for OpenCL™: ベスト・プラクティス・ガイド

ID 683521
日付 12/08/2017
Public
ドキュメント目次

2.3.2. メモリー・アクセス・パターンの例の変更

以下は、単純なOpenCLカーネルのコード例です。
kernel void big_lmem_4r_4w_nosplit (global int* restrict in, 
                                    global int* restrict out) {  
    local int lmem[4][1024]; 
 
    int gi = get_global_id(0);  
    int gs = get_global_size(0);  
    int li = get_local_id(0);  
    int ls = get_local_size(0);  
    int res = in[gi];              
    
    #pragma unroll   
    for (int i = 0; i < 4; i++) {          
         lmem[i][(li*i) % ls] = res;    
         res >>= 1;  }    

    // Global memory barrier
    barrier(CLK_GLOBAL_MEM_FENCE); 

    res = 0;  
    #pragma unroll   
    for (int i = 0; i < 4; i++) {    
        res ^= lmem[i][((ls-li)*i) % ls];  }     
    out[gi] = res;
}

この例のシステム・ビューア・レポートは、ストール可能なロードおよびストアを強調表示します。

図 16. 例のシステムビュー
図 17. 実施例のエリア・リポート
図 18. 例のカーネル・メモリー・ビューア

ロードとストアの動作の間の最初のバンクでは、アービトレーションが高い2つのメモリーバンクしか作成されないことに注意してください。次に、次のコード例に示すように、バンク・インデックスを第2次元に切り替えます。

kernel void big_lmem_4r_4w_nosplit (global int* restrict in, 
                                    global int* restrict out) {  
  local int lmem[1024][4];  

  int gi = get_global_id(0);  
  int gs = get_global_size(0);  
  int li = get_local_id(0);  
  int ls = get_local_size(0);  
  int res = in[gi];              
    
  #pragma unroll   
  for (int i = 0; i < 4; i++) {          
    lmem[(li*i) % ls][i] = res;    
    res >>= 1; 
  }    
    
  // Global memory barrier
  barrier(CLK_GLOBAL_MEM_FENCE); 
    
  res = 0;  
  #pragma unroll   
  for (int i = 0; i < 4; i++) {    
    res ^= lmem[((ls-li)*i) % ls][i];  
  }     
  out[gi] = res;
}

カーネル・メモリー・ビューアでは、4つのメモリーバンクが別々のロード・ストア・ユニットで作成されていることがわかります。すべてのロードストア命令はストールフリーです。

図 19. バンク・インデックスを変更した後の例のカーネル・メモリー・ビューア
図 20. バンク・インデックスを変更した後の例のエリア・レポート