本节书摘来自异步社区出版社《C++ AMP:用Visual C++加速大规模并行计算》一书中的第3章,第3.7节,作者: 【美】Kate Gregory , Ade Miller,更多章节内容可以访问云栖社区“异步社区”公众号查看。
3.7 使用restrict(amp)标记的函数
C++ AMP:用Visual C++加速大规模并行计算
要想成功地使用restrict(amp
)编译,函数必须遵守许多规则。头一条规则我们在3.6节中提到过,与其调用的函数有关。这些规则必须在代码生成时是可见的,也必须使用restrict(amp)
进行标记。如果我们没有使用链接时代码生成,基本上就意味着它们一定要和编译时的.cpp
文件相同,也可以使用那个.cpp文件中包含的头文件带进来。如果在编译两个.cpp
文件(一个调用函数的和一个实现函数的)时,还有链接时,使用/ltcg
开关,那么调用函数和被调用函数就可以放在各自独立的文件里。
C++ AMP兼容函数或lambda表达式只能使用C++ AMP兼容类型,它们包括:
int
unsigned int
float
double
C风格的int
、unsigned int、float
或double
数组concurrency::array
引用或concurrency::array_view
只含有C++ AMP兼容类型的结构体
这也意味着某些数据类型是禁止使用的:
bool
(可以在lambda
表达式中用于本地变量)char
short
long long
上述类型的无符号版本
引用和指针(指向兼容类型)可以在本地使用,但不能传入lambda。函数指针、指向指针的指针等不能使用;静态变量或全局变量也不能使用。
如果要使用类实例,那么类必须满足更多规则。它们不能是虚函数或虚拟继承。构造函数、析构函数以及其他非虚函数都可以使用。成员变量必须全部是兼容类型,当然也可以包含其他类的实例,只要这些类能满足相同的规则。
amp兼容函数中的实际代码不是在CPU中运行的,因此不能用来做下面的事情:
递归
指针类型转换
使用虚函数new
或delete
RTTI
或动态类型转换goto
throw
、try
或catch
访问全局变量或静态变量
内联汇编
如果我们违反了这些规则,那么看看编译器抛出的错误消息会有所帮助。下面的代码满足所有规则,可以无错编译:
std::vector<int> v(5);
std::iota(v.begin(), v.end(), 0);
array<int, 1> a(5, v.begin(), v.end());
parallel_for_each(a.extent, [&](index<1> idx) restrict(amp)
{
a[idx] = a[idx] * 2;
});```
现在把lambda中没有使用restrict(amp)标记的调用函数替换掉,但还放在同一个.cpp文件里,我们会看到下面的提示(DoubleIt是被调用函数的名字):
error C3930: 'DoubleIt' : no overloaded function has restriction specifiers that are compatible
with the ambient context`
如果函数有对应的限制,但在代码生成时不可见,那么我们也会看到这条消息。
如果我们使用short
等类型,会因为restrict(amp)
代码并不支持它们,而会看到如下的错误消息:
error C3581: 'short': unsupported type in amp restricted code
如果尝试声明指向指针的指针或者其他未经支持的类型,都会看到同样的消息。