【问题标题】:2D jagged array to 1D array in C++C ++中的二维锯齿状数组到一维数组
【发布时间】:2015-10-18 04:28:15
【问题描述】:

我需要将动态数组的动态数组转换为一维数组以进行 CUDA 计算。

示例伪代码:

x[0] = [1, 4, 3, 9]
x[1] = [2, 0]
x[2] = [5, 7, 6]

y = flatten(x)  // Eg.: [1, 4, 3, 9, 2, 0, 5, 7, 6]
get_index(a, b) // Should return index in 1D array
                // that coresponds to element in original 2D array

y[get_index(0, 2)] = 4
y[get_index(1, 0)] = 2
y[get_index(2, 2)] = 7

我发现将二维数组传递给 CUDA 内核的最佳方法是将其展平,但它仅适用于矩阵 (i=block.x*M+block.y),但不适用于每行具有不同列数的情况。

编辑:

我需要使用参数访问 1D 数组元素,就像它是 2D 一样,例如:a & b。

【问题讨论】:

  • x 只是一个数组数组,实现可能会有所不同......但元素的数量是动态的
  • 出于好奇,你在 x 上做了什么数学运算?你不能用不同的列数对那个东西做基本的矩阵数学。如果您将它们作为条目处理,则只需将行堆叠在一起 y = [x[i], x[i+1], ..., x[n]]
  • 嗯,第一维是指组ID,第二维是指节点ID,值是指另一个数组中的索引,它的值应该相加。所以没有矩阵计算。

标签: c++ arrays multidimensional-array cuda jagged-arrays


【解决方案1】:

两种可能的方法:

  1. 创建一个与最大x 维度相等的二维矩阵。因此,如果x 是一个长度为 N 的指针数组(每个指向一个向量),并且任何单个向量的最大维数是 M,则创建 C(N,M),并用一个向量填充 C 的每一行x。然后将其压平并将其转移到设备上。这种方法虽然需要额外的存储空间,但可能会在设备上产生最快的访问速度。

  2. 创建“压缩”存储格式:

    xh = [1, 4, 3, 9, 2, 0, 5, 7, 6]
    xi = [0, 4, 6]
    

    将这些向量传输到设备(它们已经是平面的)。在设备上,通过以下方式访问向量 j 的成员 i:

    myval = xh[xi[j] + i];
    

    对于这种方法,您可能还想传递一个限制向量:

    xl = [4, 2, 3]
    

    由于每次访问都可能需要通过 xi[j] 进行间接访问,因此此方法可能会导致设备上的访问速度变慢。

【讨论】:

  • 是的,我的想法与您的方法 2 相同,但我正在尝试寻找是否有更好的解决方案。
  • 如果xi 数组足够小,可以放入__constant__ 内存中,并且您可以安排统一访问(简而言之,warp 中的每个线程,给定循环,访问xi 的相同jth 元素),则可以大大减轻第二种方法的负面性能损失。
  • 这似乎是最好的方法并且效果很好,谢谢。
  • 第一个问题,@RobertCrovella 我认为你的意思是,如果一个扭曲碰巧得到不同的 j 值,(即一个扭曲跨越 j 值)然后执行变得更加低效.这有多糟糕?在这种情况下,计算出的到xh 的访问偏移量不一定会变得非本地/不连贯。第二个问题,在设备上,我将使用块或全局索引来确定这个内核应该做什么工作,从中计算出ij。我什至应该如何从该单一索引计算ij?我无法理解如何在不循环的情况下做到这一点。
  • 我没有先提到,但我应该有,谢谢你的回答,它对我帮助很大。所以我想了更多,我认为使用带有xi 数组的循环应该没问题,如果我正在循环,那么只有当扭曲恰好跨越不同的j 时,它们才会去同步。如果我的xi 的长度为 50,我不必太担心内核开头的循环最多可以运行 50 次迭代,因为我应该以这样的方式调度它以确保每个线程都会命中相同的迭代次数,得到相同的j值。
【解决方案2】:

如果您不知道每行中有多少列,我不知道用数组执行此操作的方法。尽管您可以使用迭代器范围,但有一种简单的方法可以使用向量来执行此操作。你可以这样做:

std::vector<std::vector<int>> data2d;
std::vector<int> data1d;
data1d.reserve(data2d.size() * data2d[0].size()); // reserve some memory.  this is a guess of what is needed
for (const auto row : data2d)
    data1d.insert(data1d.end(), row.begin(), row.end());

【讨论】:

  • 看起来不错,知道如何将一维向量转换为标准数组吗?因为在 CUDA 中我必须将内存完全从主机复制到 GPU 设备 - 类似于 malloc 和 memcpy 我的想法: int *std_arr = new int(data1d.size()) for(int i = 0; i
  • vecor 有一个返回底层数组的data 方法。
猜你喜欢
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-21
  • 1970-01-01
  • 2011-02-04
相关资源
最近更新 更多