在C ++ AMP中定义函数

时间:2014-01-16 18:54:24

标签: multithreading concurrency parallel-processing function-pointers c++-amp

我正在尝试编写一个卷积滤镜,它使用特定的函数来确定像素的确切输出颜色。有没有人知道是否可以定义一个可以在parallel_for_each块中使用的函数?

2 个答案:

答案 0 :(得分:3)

函数必须遵循许多规则才能使用restrict(amp)成功编译。第一,作为 parallel_for_each()部分中提到的涉及它调用的函数。那些必须是可见的 代码生成时间,也必须用restrict(amp)标记。如果您没有使用链接时间代码 生成,这实际上意味着它们必须在编译时可能来自同一个.cpp文件 该.cpp文件中包含的头文件。如果在编译两个.cpp文件(调用函数的函数和实现函数的文件)以及链接时使用/ ltcg,那么你可以保留 在单独的文件中调用和调用函数。

与C ++ AMP兼容的函数或lambda只能使用与C ++ AMP兼容的类型 包括以下内容:

  • INT
  • unsigned int
  • C样式的int,unsigned int,float或double
  • 数组
  • concurrency :: array_view或对concurrency :: array
  • 的引用
  • 仅包含C ++ AMP兼容类型的结构

这意味着禁止使用某些数据类型:

  • bool(可用于lambda中的局部变量)
  • long long
  • 上述
  • 的无符号版本

引用和指针(指向兼容类型)可以在本地使用,但不能被捕获 一个lambda。不允许使用函数指针,指针指针等;既不是静态的也不是 全局变量。

如果您希望使用它们的实例,则必须满足更多规则。它们必须没有虚函数或虚继承。允许构造函数,析构函数和其他非虚函数。该 成员变量必须都是兼容的类型,当然可以包含其他类型的实例 只要这些类符合相同的规则,就可以使用类。

放大器兼容功能中的实际代码未在CPU上运行,因此无法执行 您可能习惯做的某些事情:

  • 递归
  • 指针转换
  • 使用虚拟功能
  • new或delete
  • RTTI或动态投射

这里有一个例子,它正是你想要做的事情我想但不使用平铺。 shift参数是方形像素掩码的大小(半径)。在这个例子中,我不会尝试计算元素的新值,使其接近数组的边缘。为了不在没有工作的元素上浪费线程,parallel_for_each占用的元素小于数组shift * 2元素。更正后的索引idc会根据引用正确元素的范围调整idx值。

void MatrixSingleGpuExample(const int rows, const int cols, const int shift)
{
    //  Initialize matrices

    std::vector<float> vA(rows * cols);
    std::vector<float> vC(rows * cols);
    std::iota(vA.begin(), vA.end(), 0.0f);

    //  Calculation

    accelerator_view view = accelerator(accelerator::default_accelerator).default_view;
    double time = TimeFunc(view, [&]()
    {
        array_view<const float, 2> a(rows, cols, vA); 
        array_view<float, 2> c(rows, cols, vC);
        c.discard_data();

        extent<2> ext(rows - shift * 2, cols - shift * 2);
        parallel_for_each(view, ext, [=](index<2> idx) restrict(amp)
        {
            index<2> idc(idx[0] + shift, idx[1] + shift);
            c[idc] = WeightedAverage(idc, a, shift);
        });
        c.synchronize();
    });
}

float WeightedAverage(index<2> idx, const array_view<const float, 2>& data, int shift) 
    restrict(amp)
{
    if (idx[1] < shift || idx[1] >= data.extent[1] - shift)
        return 0.0f;
    float max = fast_math::sqrtf((float)(shift * shift * 2));
    float avg = 0.0;
    float n = 0.0f;
    for (int i = -shift; i <= shift; ++i)
        for (int j = -shift; j <= shift; ++j)
        {
            int row = idx[0] + i;
            int col = idx[1] + i;
            float scale = 1 - fast_math::sqrtf((float)((i * i) * (j * j))) / max;
            avg += data(row,col) * scale;
            n += 1.0f;
        }
    avg /= n;
    return avg;
}

答案 1 :(得分:1)

是的,如果您希望能够从CPU代码调用相同的函数,则需要使用restrict(amp)或restrict(cpu,amp)来注释函数签名。请参阅MSDN docs on restrict