【问题标题】:Defining functions in C++AMP在 C++AMP 中定义函数
【发布时间】:2014-01-16 18:54:23
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

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

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

    • int
    • 无符号整数
    • 浮动
    • C 风格的 int、unsigned int、float 或 double 数组
    • concurrency::array_view 或对 concurrency::array 的引用
    • 仅包含与 C++ AMP 兼容的类型的结构

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

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

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

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

    放大器兼容函数中的实际代码不在 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;
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      猜你喜欢
      • 2013-06-16
      • 2011-04-30
      • 1970-01-01
      • 1970-01-01
      • 2013-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多