0

我是推力(cuda)的新手,我想做一些数组操作,但我在互联网上找不到任何类似的例子。

我有以下两个数组(2d):

a = { {1, 2, 3}, {4} }
b = { {5}, {6, 7} }

我希望推力计算这个数组:

c = { {1, 2, 3, 5}, {1, 2, 3, 6, 7}, {1, 2, 3, 5}, {1, 2, 3, 6, 7} }

我知道它在 c/c++ 中是如何工作的,但不知道如何说要做它。

这是我的想法,它可能如何工作:

线程 1:取 a[0] -> 用 b 扩展它。将其写入 c。

线程 2:取 a[1] -> 用 b 扩展它。将其写入 c。

但我不知道该怎么做。我可以将数组 a 和 b 写入一维数组,例如:

thrust::device_vector<int> dev_a;
dev_a.push_back(3); // size of first array
dev_a.push_back(1);
dev_a.push_back(2);
dev_a.push_back(3);
dev_a.push_back(1); // size of secound array
dev_a.push_back(4);

thrust::device_vector<int> dev_b;
dev_b.push_back(1); // size of first array
dev_b.push_back(5);
dev_b.push_back(2); // size of secound array
dev_b.push_back(6);
dev_b.push_back(7); 

和伪函数:

struct expand
{
  __host__ __device__
  ?? ?? (const array ai, const array *b) {
      for bi in b: // each array in the 2d array
      {
          c.push_back(bi[0] + ai[0]); // write down the array count

          for i in ai: // each element in the ai array
             c.push_back(i);

          for i in bi: // each element in the bi array
             c.push_back(i);
      }
  }
};

有人知道吗?

4

1 回答 1

1

我想在这种操作中你不会在 GPU 上获得任何速度提升,因为它需要大量的内存访问——GPU 上的操作很慢。

但是,如果您无论如何都想实现这一点:

  1. 我想,出于我之前写的原因,信任不会帮助您使用现成的算法。这意味着您需要编写自己的内核,但是,您可以将内存管理留给这样。

  2. 在 CPU 内存中创建数组并在准备好后将整个数组复制到 GPU 总是更快。(CPU<->GPU 复制在较长的连续数据上更快)

  3. 请记住,GPU 并行运行数百个线程。每个线程都需要知道要读什么以及在哪里写。

  4. 全局内存操作很慢(300-400 个时钟)。避免线程从全局内存中读取整个数组以发现它只需要最后几个字节。

所以,我可以看到你的程序。

  1. 使 CPU 内存中的一维数组如下所示:

    浮点数组1[] = { 1, 2, 3, 4}; 浮点数组2[] = { 5, 6, 7}; int arr1offsets[] = {0, 2, 3, 1}; // 第一个元素的位置和子数组对的长度 int arr2offsets[] = {0, 1, 1, 2};

  2. 将您的数组和偏移量复制到 GPU 并为结果及其偏移量分配内存。我想,你必须计算一个联合子数组的最大长度并为最坏的情况分配内存。

  3. 运行内核。

  4. 收集结果

内核可能看起来像这样(如果我正确理解你的想法)

__global__ void kernel(float* arr1, int* arr1offset, 
                       float* arr2, int* arr2offset, 
                       float* result, int* resultoffset)
{
  int idx = threadIdx.x+ blockDim.x*blockIdx.x;
  int a1beg = arr1offset[Idx*2];
  int a2beg = arr2offset[Idx*2];
  int a1len = arr1offset[Idx*2+1];
  int a2len = arr2offset[Idx*2+1];
  resultoffset[idx*2] = idx*MAX_SUBARRAY_LEN;
  resultoffset[idx*2+1] = a1len+a2len;

  for (int k = 0; k < a1len; ++k) result[idx*MAX_SUBARRAY_LEN+k] = arr1[a1beg+k];
  for (int k = 0; k < a2len; ++k) result[idx*MAX_SUBARRAY_LEN+a1len+k] = arr2[a2beg+k];
}

这段代码并不完美,但应该做正确的事情。

于 2013-01-07T22:19:07.103 回答