ArrayFire 并行块求和

ArrayFire parallel block sum

我想做的是: 我在第一个(行)维度中有一个 "expanded" 数组。例如,我有一个 1080 行和 1920 列的图像。这个扩展数组是(8*1080)行和1920列,8表示"row block"大小。 我想要做的是制作一个大小为 8x1 的新数组。 这个新数组将保存第 i 个(i=0 到 7)每个块的总和。

在上面的示例中,新数组的第一个元素 (i=0) 将是扩展数组中这些像素的总和(线性索引,逐列):

0, 8(因为8是第二块的第一个元素), 16(第三块).....

再比如第二个元素:

1, 9, 17,...

我认为这可以并行化?我正在尝试解决这个问题,但我无法解决,我尝试了 gfor 但找不到解决方法,arrayfire 是不可能的吗?任何帮助表示赞赏!

我试过使用gfor,但无法解决问题。

这是我试过的一些代码:rx 是 8x1 (p_squared_1 = 8) rx_all 是扩展的 (p_squared*rows, columns) 数组。 请注意,我正在使用 seq "+" 运算符,因为如果我尝试编写 "i+p_squared_1" 会有歧义,我认为......这是我的一个错误,但我找不到另一种方法来添加一个值一个序列对象)。

af::array rx(p_squared_1, 1);
gfor(af::seq i, rows*cols*(p_squared_1-1)) {
    rx(i) = af::sum<float>(rx_all(i.operator+( (const int)p_squared_1)));
}
af::eval(rx);
cout << af::sum<float>(rx);

我希望得到一个 8x1 数组,其中每个第 i 个元素是扩展数组中每个块的第 i 个元素的总和。

我认为您可以通过执行 af::moddimsaf::sum 来实现。

array img_expanded(1080*8, 1920);

array img_expanded_reshaped = moddims(img_expanded, 8, 1920*1080);
array result = sum(img_expanded_reshaped, 1);

moddims 调用将数组重塑为 8x(1920*1080) 数组,然后您在第二个维度上执行求和。

优化布局

如果将 1920 侧作为主要维度,您可以获得更好的性能。这不仅会匹配图像在 CPU 内存中的布局,并避免在进出 GPU 时进行转置,而且重塑后的数组将具有更大的第一维,因此具有更好的 GPU 利用率。

array img_expanded(1920, 1080*8);

array img_expanded_reshaped = moddims(img_expanded, 1920*1080, 8);
array result = sum(img_expanded_reshaped, 0);

这将需要您重构比这部分代码更多的代码。