1

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

4

2 回答 2

3

一个函数必须遵循许多规则才能使用restrict(amp) 成功编译。第一个,如 parallel_for_each() 部分所述,涉及它调用的函数。这些必须在代码生成时可见,并且还必须用限制(amp)标记。如果您不使用链接时间代码生成,这实质上意味着它们必须在编译时位于同一个 .cpp 文件中,可能来自该 .cpp 文件中包含的头文件。如果在编译两个 .cpp 文件(调用函数的文件和实现函数的文件)以及链接时都使用 /ltcg,则可以将调用函数和被调用函数保存在单独的文件中。

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

  • 整数
  • 无符号整数
  • 漂浮
  • 双倍的
  • C 样式的 int、unsigned int、float 或 double 数组
  • concurrency::array_view 或对 concurrency::array 的引用
  • 仅包含 C++ AMP 兼容类型的结构

这意味着某些数据类型是被禁止的:

  • bool(可用于 lambda 中的局部变量)
  • 字符
  • 短的
  • 长长的
  • 以上的未签名版本

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

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

您的 amp 兼容函数中的实际代码未在 CPU 上运行,因此无法执行您可能习惯执行的某些操作:

  • 递归
  • 指针铸造
  • 使用虚函数
  • 新建或删除
  • 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;
}
于 2014-01-16T23:37:27.263 回答
1

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

于 2014-01-16T19:10:27.067 回答