0

に同じサイズの連続していない cl バッファーのセット (非決定論的な長さ) がありstd::vector<cl::Buffer>ます。バッファー全体で何らかの種類のピクセルごとの削減 (この場合は乗算) を実行したいと考えています。私が思いついた唯一の2つの方法(どちらも不必要なオーバーヘッドがあるようです/完全に完全に読めません)

  1. カーネルを複数回呼び出します。
  2. すべてのバッファを連続したメモリにコピーします。
  3. カーネル関数をプログラムで記述します。

そのようです

int num_values = 4;
std::stringstream kernel;
kernel << 
"__global void pix_reduce_"<<num_values<<
"  (int out*,int* a1";

for (int i = 1; i < num_values; i++)
    kernel << ",int* a"<<i;
kernel << ",int numel)" <<
"{"<<
"  const int global_idx= get_global_id(0);"<<
"  if (global_idx<numel)"<<
"  {"<<
"    int out_val = 1;";
for (int i = 0; i < num_values; i++)
  kernel << "out_val*=a"<<i<<"[global_idx];";
kernel << "out[global_idx]=out_val;}}";

これらの方法はすべてちょっと臭いです。カーネルを複数回呼び出すと、カーネル呼び出しのオーバーヘッドが何度も追加されます。バッファのコピーはまったく不要な作業です。カーネルを書くことはまったく読めず、新しいカウントごとに追加のオーバーヘッドが必要になります。これをどのように回避しますか?

4

1 に答える 1

0

各バッファの長さがわかっていて、それらすべてが等しい場合。それでは、次のように書き直してはどうでしょうか。

ホスト側:

//Use one struct to organize the data
struct MyStruct{
    cl_int values[10];
    // ...
};

//Create one only cl::Buffer of N elements of type MyStruct
cl::Buffer mybuff = cl::Buffer(context, CL_MEM_READ_ONLY, in_size * sizeof(MyStruct));

//Run the kernel

デバイス側:

//Use one struct to organize the data
typedef struct{
    int values[10];
    // ...
}MyStruct;

__global void pix_reduce
  (MyStruct out*, MyStruct* in)
{
   // ...
}

長さ「10」を X に定義し、その定義をコード (ホストおよび CPU 側) に入れることもできます。別の適切なオプションは、連続したメモリの 1 つの BIG 配列であり、分離の長さをカーネルに渡します。

注: ポインターの使用をやめるのが難しいことはわかっていますが、メモリ ゾーンが異なるため、その代償を払う必要があります。信じてください、私は非常に複雑な動的な長さの構造体を作成しましたが、少し考えて書き直すだけで機能し、コードは非常に整然としています。

編集:動的に変更できる別のソリューション

ホスト側:

//Data organized as jagged array
std::vector<std::vector<cl_int> > my_data;

//It is supposed to be filled my_Data
//....

//Create one only cl::Buffer of NxM elements of type int
cl::Buffer mybuff = cl::Buffer(context, CL_MEM_READ_ONLY, my_data.size() * my_data[0].size() * sizeof(cl_int));
cl::Buffer mybuff_out = cl::Buffer(context, CL_MEM_WRITE_ONLY, my_data.size() * my_data[0].size() * sizeof(cl_int));

// Copy the jagged array
for(int i=0; i<my_data.size(); i++)
queue.enqueueWriteBuffer(mybuff, CL_FALSE, i * my_data[0].size() * sizeof(cl_int), my_data[0].size() * sizeof(cl_int), &my_data[i][0]);

//Set kernel
kernel.SetArgs(0, mybuff);
kernel.SetArgs(1, mybuff_out);
kernel.SetArgs(2, (cl_int)my_data[0].size());

//Run the kernel
queue.EnqueueNDRangeKernel(...);

デバイス側:

__kernel void pix_reduce
  (_global const int * in, _global int * out, const int size)
{
     unsigned int id = get_global_id(0);
     for(int i=0; i<size; i++){
          out[id*size+i] = out[id*size+i]; //Or any other operation using size as the separation between chunks
     }
}
于 2013-09-17T20:45:35.220 に答える