Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+;中的每个并行#u中使用用户指定的函数+;放大器_C++_Templates_C++11_Concurrency_C++ Amp - Fatal编程技术网

C++ 在C+;中的每个并行#u中使用用户指定的函数+;放大器

C++ 在C+;中的每个并行#u中使用用户指定的函数+;放大器,c++,templates,c++11,concurrency,c++-amp,C++,Templates,C++11,Concurrency,C++ Amp,我目前正在编写一个库,我希望能够允许用户定义一个函数(声明为restrict(amp)),并允许他们将此函数传递给我的库函数之一,以便在concurrency::parallel_for_each循环中使用。例如: template <typename T, typename Func> void Foo( const concurrency::array_view<const T>& avParam, Func f ) { concurrency::

我目前正在编写一个库,我希望能够允许用户定义一个函数(声明为
restrict(amp)
),并允许他们将此函数传递给我的库函数之一,以便在
concurrency::parallel_for_each
循环中使用。例如:

template <typename T, typename Func>
void Foo( const concurrency::array_view<const T>& avParam, Func f ) 
{
     concurrency::array<T, 1> arrResult( avParam.extent );
     concurrency::parallel_for_each( avParam.extent, [=, &arrResult]( concurrency::index<1> index ) restrict(amp) {
          arrResult[index] = f( avParam[index] );
     } );

     // Do stuff...
}
模板
void Foo(const并发::array_view&avParam,Func f)
{
并发::数组arresult(avParam.extent);
并发性::每个(avParam.extent,[=,&arrResult](并发性::索引)的并行性限制(amp){
arresult[index]=f(avParam[index]);
} );
//做些事情。。。
}
如果
f
被声明为有效的AMP兼容函数,我希望这能起作用,就像我直接用内核中的函数本身替换函数指针
f
;一切正常。但是,使用
f
会导致以下错误:

不支持函数指针、函数引用或指向成员函数的指针

是否有任何方法可以在不阻止用户使用lambdas以外的函数的情况下获得所需的行为?

我这里没有windows框,因此无法复制或测试它

不支持函数指针、函数引用或指向成员函数的指针

这意味着

  • 类似于“
    R(*pf)(T)
    中的函数指针“pf”必须至少由
    std::function func(pf)

  • 此时,
    func
    应该像在
    std::forward(in_func)
    中将调用堆栈传递给函数[in]
    in_func

  • 不管怎样,mem_fun_PTR都是关闭的

从[SKJJ12]p9中,我认为该函数以及调用堆栈中的所有函数或函数对象也需要标记为
restrict(amp)
,并实现该概念

[SKJJ12] Sharlet, Kunze, Junkins Joshi 
Shevlin Park: Implementing C++ AMP with Clang/LLVM and OpenCL
http://llvm.org/devmtg/2012-11/Sharlet-ShevlinPark.pdf
引用和指针(指向兼容类型)可以在本地使用,但不能被lambda捕获。不允许使用函数指针、指向指针的指针等;既不是静态变量也不是全局变量

如果希望使用类的实例,则类必须满足更多规则。它们必须没有虚拟函数或虚拟继承。允许使用构造函数、析构函数和其他非虚函数。成员变量必须都是兼容的类型,当然可以包括其他类的实例,只要这些类满足相同的规则。amp兼容函数中的实际代码未在CPU上运行,因此无法执行某些您可能习惯于执行的操作:

  • 递归
  • 指针铸造
  • 虚拟函数的使用
  • 新建或删除
  • RTTI或动态铸造
您应该使用函数的lambda编写库,因为可以使用restrict(amp)内核访问这些函数。您可以执行以下操作:

template <typename T, typename Func>
void Foo(const concurrency::array_view<const T>& avParam, Func f)
{
    concurrency::array<T, 1> arrResult(avParam.extent);
    concurrency::parallel_for_each(avParam.extent, [=, &arrResult](concurrency::index<1> index) restrict(amp) 
    {
        arrResult[index] = f(avParam[index]);
    });

    // Do stuff...
}

template <typename T>
class Bar
{
public:
    T operator()(const T& v) const restrict(amp)
    {
        return v + 2;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<int> result(100, 0);
    array_view<const int, 1> result_av(result.size(), result);

    Foo(result_av, Bar<int>());

    return 0;
}
模板
void Foo(const并发::array_view&avParam,Func f)
{
并发::数组arrResult(avParam.extent);
并发性::每个(avParam.extent,[=,&arrResult](并发性::索引)的并行性限制(amp)
{
arresult[index]=f(avParam[index]);
});
//做些事情。。。
}
模板
分类栏
{
公众:
T运算符()(常数T&v)常数限制(amp)
{
返回v+2;
}
};
int _tmain(int argc,_TCHAR*argv[]
{
std::向量结果(100,0);
数组\查看结果\ av(result.size(),result);
Foo(result_av,Bar());
返回0;
}

一种考虑这一点的方法是,函数或lambda等效项创建一个容器,编译器可以确保它没有依赖关系,并且C++运行时可以在GPU上实例化。这将很难用函数指针实现

假设我们有:

template <typename T, typename Func>
void Foo( const concurrency::array_view<const T>& avParam, Func f ) 

int f(int x) restrict(amp) {return x+2;}
它不是指向
f
的函数指针,而是创建一个不使用函数指针的lambda

我们可以自动化这个

#define AMP_OVERLOAD_SET(F) struct { \
  template<typename... Args> auto operator()(Args&&...args)const restrict(amp) \
  ->decltype( F(std::declval<Args>()...) ) \
  { return F( std::forward<Args>(args)... ); } \
}

static AMP_OVERLOAD_SET(f) amped_f; // declare an overload set object for `f`
Foo( vParam, amped_f ); // pass it to `Foo`
#定义AMP_重载_集(F)结构{\
模板自动运算符()(Args&&…Args)常量限制(amp)\
->decltype(F(std::declval()…)\
{返回F(std::forward(args)…);}\
}
静态放大器过载设置(f)放大器f;//为'f'声明重载集对象`
Foo(vParam,amped_f);//把它传给‘福’`

这可能有效,也可能无效。

@downvoter为什么你觉得这个问题没有建设性,对其他人没有好处?@downvoter我支持Shaktai的问题。Imnsho这是一个对从事并行编程的人们来说最有价值的问题。对我来说,这似乎是一个完全合理的问题。我们回答了你的问题吗?这不只是声明函子的另一种方式吗?@Ademillar两者都是肯定的。只调用相关函数的函子,这绕过了“无函数指针”规则。第一个是在本地执行的,使用一个内联lambda调用
f
。第二个实现了名为
f
的所有函数的重载集,并允许您传递它。有可能
restrict(amp)
不允许使用该语法。我尝试了此操作,但无法使用以下模板参数编译“错误C2893:无法专门化函数模板的未知类型::运算符()(Args&&…)restrict(amp)const:'Args={const int&}“@AdeMiller Expression SFINAE可能有问题?或者可能是AMP方法上的引用参数限制?不确定。您是否知道是否有计划扩展C++AMP语言的功能,以允许以
restrict(AMP)
标记的函数指针(可能具有适当的常量(expr)-ness)?
#define AMP_OVERLOAD_SET(F) struct { \
  template<typename... Args> auto operator()(Args&&...args)const restrict(amp) \
  ->decltype( F(std::declval<Args>()...) ) \
  { return F( std::forward<Args>(args)... ); } \
}

static AMP_OVERLOAD_SET(f) amped_f; // declare an overload set object for `f`
Foo( vParam, amped_f ); // pass it to `Foo`