我目前正在编写库,我希望能够允许用户定义一个函数(声明为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...
}
我希望这可以工作,提供f
被声明为有效的AMP兼容函数,就像我直接用函数本身替换函数指针f
一样;一切都按预期工作。但是,使用f
会导致以下错误:
不支持函数指针,函数引用或指向成员函数的指针。
在没有阻止我的用户使用除lambdas之外的仿函数的情况下,我有什么方法可以获得我想要的行为吗?
答案 0 :(得分:2)
引用和指针(到兼容类型)可以在本地使用,但不能由lambda捕获。不允许使用函数指针,指针指针等;既不是静态变量也不是全局变量。
如果您希望使用它们的实例,则必须满足更多规则。它们必须没有虚函数或虚继承。允许构造函数,析构函数和其他非虚函数。成员变量必须都是兼容的类型,当然可以包括其他类的实例,只要这些类满足相同的规则。放大器兼容功能中的实际代码未在CPU上运行,因此无法执行您可能习惯的某些事情:
- 递归
- 指针转换
- 使用虚拟功能
- new或delete
- RTTI或动态投射
您应该根据仿函数的lambdas编写库,因为可以使用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;
}
考虑这一点的一种方法是functor或lambda等效创建一个容器,编译器可以确保它没有依赖关系,并且C ++ AMP运行时可以在GPU上实例化。使用函数指针实现这一点要困难得多。
答案 1 :(得分:0)
我这里没有窗框,所以无法复制或测试。
不支持函数指针,函数引用或指向成员函数的指针。
这意味着
一个函数指针&#39; pf&#39;喜欢在&#39; R (*pf) (T)
必须至少包含std::function<R(T)> func(pf)
在func
传递调用堆栈到函数[{1}}
和mem_fun_pt都已关闭。
从[SKJJ12]第9页我认为那个函数,以及调用堆栈中的所有函数或函数对象,也需要标记为std::forward<std::function<R(T)>>(in_func)
并实现该概念。
in_func
答案 2 :(得分:0)
假设我们有:
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;}
然后尝试:
Foo( avParam, [](int x) restrict(amp){ return f(x); } );`
而不是指向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`
可能有效也可能无效。