在C ++并行放大器几个算术运算(Several arithmetic operations par

2019-10-19 04:24发布

我试图用并行C ++放大器卷积滤镜。 我想下面的功能开始工作(我不知道该怎么做正确):

float* pixel_color[] = new float [16]; 

concurrency::array_view<float, 2> pixels(4, 4, pixel_array), taps(4, 4, myTap4Kernel_array); 
concurrency::array_view<float, 1> pixel(16, pixel_color); // I don't know which data structure to use here

parallel_for_each(
      pixels.extent, [=](concurrency::index<2> idx) restrict(amp)
  {
      int row=idx[0];
      int col=idx[1];

      pixels(row, col) = taps(row, col) * pixels(row, col); 
      pixel[0] += pixels(row, col); 
     });
pixel_color.synchronize(); 

pixels_.at<Pixel>(j, i) = pixel_color 

}

主要的问题是,我不知道如何正确使用的像素结构(这里使用的并发数据结构 ,因为我并不需要所有16种元素)。 我不知道是否可以安全地添加值这种方式。 下面的代码不工作,它不添加适当的值[0]像素中。 我也想定义

concurrency::array_view<float, 2> pixels(4, 4, pixel_array), taps(4, 4, myTap4Kernel_array); 

该方法之外(例如在头文件),并在costructor或其它功能初始化(因为这是一个瓶颈和花费大量的时间复制CPU和GPU之间的数据)。 有人知道怎么做这个吗?

Answer 1:

你没有在正确的轨道,但在GPU上的阵列的地方操作做的是棘手,因为你不能保证在不同的元素被更新的顺序。

这里有一些非常相似的例子。 该ApplyColorSimplifierTiledHelper方法包含AMP限制parallel_for_each调用SimplifyIndexTiled用于2D阵列中的每个索引。 SimplifyIndexTiled计算中的每个像素的新值destFrame基于围绕在对应的像素的像素的值srcFrame 。 这解决了存在于你的代码中的竞争条件问题。

此代码来自Codeplex上现场为C ++ AMP书 。 所述卡通化案例研究包括这些种类的使用在C ++ AMP实现图像处理的问题的几个例子; 阵列,纹理,平铺/ untiled和多GPU。 在C ++ AMP本书讨论了一些细节的落实。

void ApplyColorSimplifierTiledHelper(const array<ArgbPackedPixel, 2>& srcFrame,
    array<ArgbPackedPixel, 2>& destFrame, UINT neighborWindow)
{
    const float_3 W(ImageUtils::W);

    assert(neighborWindow <= FrameProcessorAmp::MaxNeighborWindow);

    tiled_extent<FrameProcessorAmp::TileSize, FrameProcessorAmp::TileSize>     
        computeDomain = GetTiledExtent(srcFrame.extent);
    parallel_for_each(computeDomain, [=, &srcFrame, &destFrame]
        (tiled_index<FrameProcessorAmp::TileSize, FrameProcessorAmp::TileSize> idx) 
        restrict(amp)
    {
        SimplifyIndexTiled(srcFrame, destFrame, idx, neighborWindow, W);
    });
}

void SimplifyIndex(const array<ArgbPackedPixel, 2>& srcFrame, array<ArgbPackedPixel,
                   2>& destFrame, index<2> idx, 
                   UINT neighborWindow, const float_3& W) restrict(amp)
{
    const int shift = neighborWindow / 2;
    float sum = 0;
    float_3 partialSum;
    const float standardDeviation = 0.025f;
    const float k = -0.5f / (standardDeviation * standardDeviation);

    const int idxY = idx[0] + shift;         // Corrected index for border offset.
    const int idxX = idx[1] + shift;
    const int y_start = idxY - shift;
    const int y_end = idxY + shift;
    const int x_start = idxX - shift;
    const int x_end = idxX + shift;

    RgbPixel orgClr = UnpackPixel(srcFrame(idxY, idxX));

    for (int y = y_start; y <= y_end; ++y)
        for (int x = x_start; x <= x_end; ++x)
        {
            if (x != idxX || y != idxY) // don't apply filter to the requested index, only to the neighbors
            {
                RgbPixel clr = UnpackPixel(srcFrame(y, x));
                float distance = ImageUtils::GetDistance(orgClr, clr, W);
                float value = concurrency::fast_math::pow(float(M_E), k * distance * distance);
                sum += value;
                partialSum.r += clr.r * value;
                partialSum.g += clr.g * value;
                partialSum.b += clr.b * value;
            }
        }

    RgbPixel newClr;
    newClr.r = static_cast<UINT>(clamp(partialSum.r / sum, 0.0f, 255.0f));
    newClr.g = static_cast<UINT>(clamp(partialSum.g / sum, 0.0f, 255.0f));
    newClr.b = static_cast<UINT>(clamp(partialSum.b / sum, 0.0f, 255.0f));
    destFrame(idxY, idxX) = PackPixel(newClr);
}

该代码使用ArgbPackedPixel ,这简直是用于包装8位RGB值转换成一个的机构unsigned long为C ++ AMP不支持char 。 如果你的问题是小到足以放入一个纹理,那么你可能想看看使用,而不是作为包/解包在硬件中实现对GPU数组中此所以是有效的“自由”,在这里你必须为它付出额外的计算。 还有CodePlex上这个实现的一个例子。

typedef unsigned long ArgbPackedPixel;

struct RgbPixel 
{
    unsigned int r;
    unsigned int g;
    unsigned int b;
};

const int fixedAlpha = 0xFF;

inline ArgbPackedPixel PackPixel(const RgbPixel& rgb) restrict(amp) 
{
    return (rgb.b | (rgb.g << 8) | (rgb.r << 16) | (fixedAlpha << 24));
}


inline RgbPixel UnpackPixel(const ArgbPackedPixel& packedArgb) restrict(amp) 
{
    RgbPixel rgb;
    rgb.b = packedArgb & 0xFF;
    rgb.g = (packedArgb & 0xFF00) >> 8;
    rgb.r = (packedArgb & 0xFF0000) >> 16;
    return rgb;
}


文章来源: Several arithmetic operations parallelized in C++Amp