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框,因此无法复制或测试它
不支持函数指针、函数引用或指向成员函数的指针
这意味着
- 类似于“
中的函数指针“pf”必须至少由R(*pf)(T)
std::function func(pf)
- 此时,
应该像在func
中将调用堆栈传递给函数[in]std::forward(in_func)
in_func
- 不管怎样,mem_fun_PTR都是关闭的
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或动态铸造
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`