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

简介:

本节书摘来自异步社区出版社《C++ AMP:用Visual C++加速大规模并行计算》一书中的第3章,第3.8节,作者: 【美】Kate Gregory , Ade Miller,更多章节内容可以访问云栖社区“异步社区”公众号查看。

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`会提醒我们。
相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
相关文章
|
弹性计算 人工智能 Serverless
阿里云ACK One:注册集群云上节点池(CPU/GPU)自动弹性伸缩,助力企业业务高效扩展
在当今数字化时代,企业业务的快速增长对IT基础设施提出了更高要求。然而,传统IDC数据中心却在业务存在扩容慢、缩容难等问题。为此,阿里云推出ACK One注册集群架构,通过云上节点池(CPU/GPU)自动弹性伸缩等特性,为企业带来全新突破。
|
监控 异构计算
Jetson 学习笔记(八):htop查看CPU占用情况和jtop监控CPU和GPU
在NVIDIA Jetson平台上使用htop和jtop工具来监控CPU、GPU和内存的使用情况,并提供了安装和使用这些工具的具体命令。
1385 0
|
机器学习/深度学习 人工智能 并行计算
CPU和GPU的区别
【10月更文挑战第14天】
|
机器学习/深度学习 人工智能 缓存
GPU加速和CPU有什么不同
【10月更文挑战第20天】GPU加速和CPU有什么不同
670 1
|
存储 并行计算 数据处理
使用GPU 加速 Polars:高效解决大规模数据问题
Polars 最新开发了 GPU 加速执行引擎,支持对超过 100GB 的数据进行交互式操作。本文详细介绍了 Polars 中 DataFrame(DF)的概念及其操作,包括筛选、数学运算和聚合函数等。Polars 提供了“急切”和“惰性”两种执行模式,后者通过延迟计算实现性能优化。启用 GPU 加速后,只需指定 GPU 作为执行引擎即可大幅提升处理速度。实验表明,GPU 加速比 CPU 上的懒惰执行快 74.78%,比急切执行快 77.38%。Polars 的查询优化器智能管理 CPU 和 GPU 之间的数据传输,简化了 GPU 数据处理。这一技术为大规模数据集处理带来了显著的性能提升。
843 4
|
人工智能 自然语言处理 文字识别
MinerU-大语言语料处理神器,CPU/GPU均可跑,开源免费“敲”好用
在7月4日举行的WAIC 2024科学前沿主论坛上,书生·浦语2.5正式发布,面向大模型研发与应用的全链条工具体系同时迎来升级。
MinerU-大语言语料处理神器,CPU/GPU均可跑,开源免费“敲”好用
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
10月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
419 12
|
8月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
226 0
|
8月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
357 0

热门文章

最新文章