《C++ AMP:用Visual C++加速大规模并行计算》——3.8 在CPU和GPU之间复制数据

3.8 在CPU和GPU之间复制数据

C++ AMP:用Visual C++加速大规模并行计算
数据可以在CPU和加速器(通常是GPU)之间自动复制,也可以根据需要使用amp.h中众多的copy()重载函数之一显式复制。例如,我们可以在默认加速器上构造array,然后仅使用一条函数调用便可以把数据复制进去:

array<int, 1> a(5, v.begin(), v.end());
此外,我们还可以构造空数组,然后再使用copy()函数来加载数据。array_view在CPU上有一个对应容器,当加速器上的array_view开始处理时,array_view会自动把数据复制到加速器里,并把发生变化的数据同步回去在CPU上使用,如3.5节所述。

这两段代码段是等价的:

std::vector<int> v(5);                std::vector<int> v(5);
std::iota(v.begin(), v.end(), 0);          std::iota(v.begin(), v.end(), 0);
array<int,1> a(5,v.begin(),v.end());        array_view<int,1> av(5,v);
parallel_for_each(a.extent, [&](index<1> idx)   parallel_for_each(av.extent, [=]                                 (index<1> idx)
  restrict(amp)                      restrict(amp) 
{                             {
  a[idx] = a[idx]  2;                  av[idx] = av[idx]  2;
});                            });  
copy(a,v);                        av.synchronize();```
如果要在`parallel_for_each`之后访问CPU上的`array_view`,它将自动同步,因此我们可以忽略这条调用。这是使用`array_view`最大的优势所在。

当然,自动复制如非真正需要便会造成性能受损。C++ AMP让我们可以真正控制自动复制。在声明`array_view`的时候,我们可以给编译器一个暗示,说明数据将要发送到加速器上,但不会在那里改变:

`array_view<const int, 1> a(5, v);`
这么做会防止自动将加速器数据复制返回。这种聪明的关键词和概念复用方法,已为C++开发者所熟知。我们还可以暗示无需把初始值复制到加速器里,因为核函数会重写这些初始值,例如:

array_view out(5, v2);
out.discard_data();``
C++里没有
writeonly关键词(或anti_const`),因此我们要代而使用这种函数调用。

还有一种方法可以从array_view中取出数据并返还给它所包装的CPU集合,以便array_view作析构之用。例如,这种代码即使在没有调用synchronize的情况下,也可以让计算结果出现在std::vector v2中:

std::vector<int> v(5), v2(5, 0);
std::iota(v.begin(), v.end(), 0);
// braces for scope only
{
  array_view<const int, 1> a(5, v);
  array_view<int, 1> out(5, v2);
  out.discard_data();
  parallel_for_each(a.extent, [=](index<1> idx) restrict(amp)
  {
    out[idx] = a[idx] * 2;
  });
}```
对于数组视图来说,作用域结束的时候就会自动执行复制,这时const暗示的重要性就凸显出来了,因为我们不需要把没有改变的值从a复制回v,而暗示会阻止这种操作的发生。

任何时候,我们都可以显式地从一个数组把数据复制到另一个数组,或者从一个array_view把数据复制到另一个,或者从一个数组复制到std::vector等位于CPU的集合中。复制的两个参数分别是源和地址。

注意事项:
受限于对标准库方法的掌握程度,我们会发现要想记住参数顺序并非很容易,标准库方法大多以源作为第一个参数,而C风格函数一般会把目标作为第一个参数。但是,我们必须要选择一个参数顺序,它可能更像是标准库而不像C。C++ AMP的设计师一般要遵循C++约定,而非C约定。如果需要提示,`IntelliSense`会提醒我们。
任何两个进行数据复制的容器都要在元素类型和元素数目上相匹配。如果两个容器都有秩(`array`到`array`、`array`到`array_view`、`array_view`到`array_view`,或者`array_view`到`array`),那么秩也必须匹配。我们可以使用支持迭代器的标准容器。
时间: 2024-10-31 01:00:36

《C++ AMP:用Visual C++加速大规模并行计算》——3.8 在CPU和GPU之间复制数据的相关文章

《C++ AMP:用Visual C++加速大规模并行计算》——第3章 C++ AMP基础

第3章 C++ AMP基础 C++ AMP:用Visual C++加速大规模并行计算通过本章的学习,读者将会了解: arrayaccelerator与accelerator_viewindexextentarray_viewparallel_for_each使用restrict(amp)标记的函数在CPU和GPU之间复制数据数学库函数小结

《C++ AMP:用Visual C++加速大规模并行计算》——1.2 CPU并行技术

1.2 CPU并行技术 C++ AMP:用Visual C++加速大规模并行计算 减少应用程序串行部分耗时的一种方法是尽量降低其串行性,重新设计应用程序,充分利用CPU并行和GPU并行.虽然GPU可以同时拥有成千上万个线程,而CPU要少得多,但利用CPU的并行性也能对整体加速比有所帮助.理想情况下,CPU并行技术和GPU并行技术是兼容的,方法也有很多. 1.2.1 向量化 SIMD是一种能使处理速度变得更快的重要方法,也即单指令流多数据流(Single Instruction, Multiple

《C++ AMP:用Visual C++加速大规模并行计算》——1.3 C++ AMP方法

1.3 C++ AMP方法 C++ AMP:用Visual C++加速大规模并行计算 C++ AMP是一个并行库和语言层面的小扩展,能够帮助在C++应用程序中实现异构计算.(AMP是Accelerated Massive Parallelism的缩写,即加速大规模并行.)Visual Studio提供了新的工具和功能支持,可以用来调试和剖析C++ AMP应用程序的性能,包括GPU调试和GPU并行可视化.有了C++ AMP以后,主流C++开发人员可以使用熟悉的工具来创建可移植的.不会过时的应用程序

《C++ AMP:用Visual C++加速大规模并行计算》——1.1 为什么选择GPGPU?什么是异构计算?

1.1 为什么选择GPGPU?什么是异构计算? C++ AMP:用Visual C++加速大规模并行计算 作为开发者,面对周围不断变化的世界,努力调整自己,这种生活我们早已习以为常.IT行业对世界的影响自成体系.我们学习新的语言,使用新的方法,考虑采用新的用户界面,并理所当然地认为它们都能让我们的程序变得更好.为了让下一版比上一版更完善,如果认为采用某种方法会碰壁,我们就会转而换用另外一种方法.而有些开发者现在要使用的最新方法就是异构计算. 本章将回顾计算性能提升的历史,让读者们看看开发者们都碰

《C++ AMP:用Visual C++加速大规模并行计算》——3.9 数学库函数

3.9 数学库函数 C++ AMP:用Visual C++加速大规模并行计算 如前所述,我们不能只在parallel_for_each中调用来自"核函数"的函数.调用函数应该在代码生成时可见,应该使用restrict(amp)标记.如果我们要转换现有代码,就需要做出必要的调整.我们也有可能会调用sqrt()或sin()等库函数.因此,需要使用加速器兼容版本替换这些调用.好消息是amp_math.h里定义了成百上千的此类函数,它们全都在命名空间concurrency::fast-math

《C++ AMP:用Visual C++加速大规模并行计算》——3.1 array &lt; T,N &gt;

3.1 array < T,N > C++ AMP:用Visual C++加速大规模并行计算 对于C++ AMP开发者来说,头等重要的就是array.array模板位于concurrency命名空间,有两个参数:一个是集合元素的类型,另一个是秩(rank)或者说维数.我们日常工作中使用的多是一维.二维或三维数组,但C++ AMP并没有限制我们只用到三维,如果我们需要,最多可以用到128维! 正常情况下,array是加速器(一般是GPU)上的一组信息(相同类型的).array其实是在accele

《C++ AMP:用Visual C++加速大规模并行计算》——第1章 C++ AMP概述

第1章 C++ AMP概述 C++ AMP:用Visual C++加速大规模并行计算 通过本章的学习,读者将会了解: 为什么选择GPGPU?什么是异构计算? CPU并行技术 C++ AMP方法 小结

《C++ AMP:用Visual C++加速大规模并行计算》——3.7 使用restrict(amp)标记的函数

3.7 使用restrict(amp)标记的函数 C++ AMP:用Visual C++加速大规模并行计算 要想成功地使用restrict(amp)编译,函数必须遵守许多规则.头一条规则我们在3.6节中提到过,与其调用的函数有关.这些规则必须在代码生成时是可见的,也必须使用restrict(amp)进行标记.如果我们没有使用链接时代码生成,基本上就意味着它们一定要和编译时的.cpp文件相同,也可以使用那个.cpp文件中包含的头文件带进来.如果在编译两个.cpp文件(一个调用函数的和一个实现函数的

《C++ AMP:用Visual C++加速大规模并行计算》——1.4 小结

1.4 小结 C++ AMP:用Visual C++加速大规模并行计算 本章描述了异构计算适合处理的问题类型,以及过去数十年间应用程序性能提升的历史.还介绍了C++ AMP,解释了设计C++ AMP的动机.本书其余各部分将会更详细地解释C++ AMP的类库和语言扩展,演示如何使用更先进的技术,使应用程序获得最大的性能提升,展示如何使用Visual Studio的支持功能.有些主流开发人员对通过C++ AMP利用异构感兴趣,本书也为他们提供了指导.