1

CUDA を使用して数値の配列を並列化するのに問題があります。

たとえば、数値 ( 1 、 2 、 3 、 4 、 5) を含む配列 M があるとします。

そして、配列内の数値 2 を削除してすべてを左にシフトすると、結果の配列は ( 1 , 3 , 4 , 5 , 5 ) になります。

ここで、M[1] = M[2]、M[2] = M[3]、M[3] = M[4]

そして私の質問は、cudaでこれをどのように並行して行うことができるでしょうか? これを並列化すると、数値 2 (M[1]) が最初に動作する最初のものではない可能性がある競合状態が発生する可能性があるため、M[2] が最初にシフトするものである場合、結果の配列は ( 1 、4、4、5、5)。これを処理する方法はありますか?私はcudaにかなり慣れていないので、何をすべきかわかりません...

私の現在のコードは次のとおりです。

__global__ void gpu_shiftSeam(int *MCEnergyMat, int *seam, int width, int height, int currRow)
{
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    int j = blockIdx.y * blockDim.y + threadIdx.y;

    int index = i+width*j;

    if(i < width && j <height)
    {
        //shift values of -1 to the side of the image
        if(MCEnergyMat[i+width*j] == -1)
        {
            if(i+1 != width)
                    MCEnergyMat[index] = MCEnergyMat[index+1];
        }
        if(seam[j] < i)
        {
            if(i+1 != width)
                MCEnergyMat[index] = MCEnergyMat[index+1];
        }
    }
}

Whereseam[i]には、配列から削除したいインデックスが含まれています。2次元配列から変換さMCEnergyMatれた単なる1次元配列です...ただし、私のコードは機能しません...そして、競合状態が問題だと思います。

ありがとう!

4

1 に答える 1

1

talonmies がコメントで指摘しているように、この種のことは「ストリーム圧縮」と呼ばれます。Thrustでそれを行う方法は次のとおりです。

#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/remove.h>
#include <iostream>

int main()
{
  int data[5] = {1,2,3,4,5};
  thrust::device_vector<int> d_vec(data, data + 5);

  // new_end points to the end of the sequence after 2 has been thrown out
  thrust::device_vector<int>::iterator new_end = 
    thrust::remove(d_vec.begin(), d_vec.end(), 2);

  // erase everything after the new end
  d_vec.erase(new_end, d_vec.end());

  // prove that it worked
  thrust::host_vector<int> h_vec = d_vec;

  std::cout << "result: ";
  thrust::copy(h_vec.begin(), h_vec.end(), std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

  return 0;
}

結果は次のとおりです。

$ nvcc test.cu -run result: 1 3 4 5

于 2012-04-25T23:22:20.323 に答える