0

実行を高速化するために、ローカルメモリを使用してopenclでカーネルを作成しました。ローカルメモリを使用するのはこれが初めてです。私のglobal_work_size=16およびlocal_work_size=8。

Openclカーネル:mapper.cl

#pragma OPENCL EXTENSION cl_khr_fp64 : enable
typedef struct data
{
  double dattr[10];
  int d_id;
  int bestCent;
}Data;


typedef struct cent
{
  double cattr[5];
  int c_id;
}Cent;

__kernel void mapper(__global int *keyMobj, __global int *valueMobj, __global Data *dataMobj, __global Cent *centMobj)
{
    int bx   = get_group_id(0);    
    int tx   = get_local_id(0);
    int size = get_local_size(0);

    __local double localData[8][2];
    __local double localCent[2][2];
    __local int local_id[8];

    int index = tx + bx*size;

    int j,k,color=0;
    double dmin=1000000.0, dx;

    for(j=0; j<2; j++)
    {
          if(tx<2)
              localCent[tx][j] = centMobj[tx].cattr[j];

          localData[tx][j] = dataMobj[index].dattr[j];
          local_id[tx] = dataMobj[index].d_id;

    }
barrier(CLK_LOCAL_MEM_FENCE); 


    for(j=0; j<2; j++)     
     {
        dx = 0.0;
        for(k=0; k<2; k++)
            dx+= ((localCent[j][k] - localData[index][k]) * (localCent[j][k] - localData[index][k]));

        if(dx<dmin)            
        {  color = j;   
           dmin = dx;
        }
     }  
    keyMobj[index]   = color;
    valueMobj[index] = local_id[tx];
}

上記のカーネルでは、構造体dataMobjの最初の8つのオブジェクトとcentMobjの2つのオブジェクトを、それぞれグローバルメモリからローカルメモリlocalDataとlocalCentにフェッチしています。私のプログラミングに関する限り、データフェッチ用の適切なforループを使用しました。

ただし、最初の8つの作業項目(最初の作業グループの場合)のみが正しく実行されます。残りのブロックの次の残りの8つの作業項目を使用してデータをフェッチしません。

これが正確にどのように機能するかを教えてください。問題が発生した場合はお知らせください。また、スレッドの同期にメモリフェンスを使用しました。

4

1 に答える 1

3

このプログラムの問題は、配列の範囲を超えていることです。これは、8つの作業項目だけで適切な結果を達成できるが、16では達成できない理由を説明しています。

localDatalocalは、メモリ空間内のdoubleの配列の配列です。

 __local double localData[8][2];

変数もありますindex。これは次のように定義されます。

int index = tx + bx*size;
//get_local_id(0) + get_group_id(0) * get_local_size(0) = get_global_size(0)

16個の作業項目の場合、インデックス範囲の値は[0〜15]です。次の行:

dx+= ((localCent[j][k] - localData[index][k])
     * (localCent[j][k] - localData[index][k]));

ローカル配列の範囲は[0-8]のみですが、localData変数は変数を使用して参照されます。index

于 2013-01-28T22:02:44.483 に答える