C++编程笔记(GPU并行编程-2)
C++与CUDA
内存管理
封装
利用标准库容器实现对GPU的内存管理
#include <iostream>
#include <cuda_runtime.h>
#include <vector>
#include <cstddef>
template<class T>
struct CUDA_Allocator {
using value_type = T; //分配器必须要有的
T *allocate(size_t size) {
T *dataPtr = nullptr;
cudaError_t err = cudaMallocManaged(&dataPtr, size * sizeof(T));
if (err != cudaSuccess) {
return nullptr;
}
return dataPtr;
}
void deallocate(T *ptr, size_t size = 0) {
cudaError_t err = cudaFree(ptr);
}
};
__global__ void kernel(int *arr, int arrLen) {
for (int i = blockDim.x * blockIdx.x + threadIdx.x; i < arrLen; i += blockDim.x * gridDim.x) {
arr[i] = i;
//printf("i=%d\n", i);
}
}
int main() {
int size = 65523;
std::vector<int, CUDA_Allocator<int>> arr(size);
kernel<<<13, 28>>>(arr.data(), size);
cudaError_t err = cudaDeviceSynchronize();
if (err != cudaSuccess) {
printf("Error:%s\n", cudaGetErrorName(err));
return 0;
}
for (int i = 0; i < size; ++i) {
printf("arr[%d]=%d\n", i, arr[i]);
}
}
其中allocate和deallocate是必须实现的
这里不用默认的std::allocate,使用自己定义的分配器,使得内存分配在GPU上
vector是会自动初始化的,如果不想自动初始化的化,可以在分配器中自己写构造函数
关于分配器的更多介绍
函数调用
template<class Func>
__global__ void para_for(int n, Func func) {
for (int i = blockDim.x * blockIdx.x + threadIdx.x; i < n; i += blockDim.x * gridDim.x) {
func(i);
}
}
//定义一个仿函数
struct MyFunctor {
__device__ void operator()(int i) {
printf("number %d\n", i);
}
};
int main() {
int size = 65513;
para_for<<<13,33>>>(size,MyFunctor{});
cudaError_t err = cudaDeviceSynchronize();
if (err != cudaSuccess) {
printf("Error:%s\n", cudaGetErrorName(err));
return 0;
}
}
同样的,lambda也是被支持的,但是要先在cmake中开启
target_compile_options(${PROJECT_NAME} PUBLIC $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda>)

lambda
lambda写法
para_for<<<13, 33>>>(size, [] __device__(int i) { printf("number:%d\n", i); });
lambda捕获外部变量
一定要注意深拷贝和浅拷贝
如果这里直接捕获arr的话,是个深拷贝,这样是会出错的,因为拿到的arr是在CPU上的,而数据是在GPU上的,所以这里要浅拷贝指针,拿到指针的值,就是数据在GPU上的地址,这样就可以使用device函数对数据进行操作了
std::vector<int, CUDA_Allocator<int>> arr(size);
int*arr_ptr=arr.data();
para_for<<<13, 33>>>(size, [=] __device__(int i) { arr_ptr[i] = i; });
cudaError_t err = cudaDeviceSynchronize();
if (err != cudaSuccess) {
printf("Error:%s\n", cudaGetErrorName(err));
return 0;
}
for (int i = 0; i < size; ++i) {
printf("arr[%d]=%d\n", i, arr[i]);
}
同时还可以这样捕获
para_for<<<13, 33>>>(size, [arr=arr.data()] __device__(int i) { arr[i] = i; });
时间测试
#include <chrono>
#define TICK(x) auto bench_##x = std::chrono::steady_clock::now();
#define TOCK(x) std::cout << #x ": " << std::chrono::duration_cast<std::chrono::duration<double> >(std::chrono::steady_clock::now() - bench_##x).count() << "s" << std::endl;
int main(){
int size = 65513;
std::vector<float, CUDA_Allocator<float>> arr(size);
std::vector<float> cpu(size);
TICK(cpu_sinf)
for (int i = 0; i < size; ++i) {
cpu[i] = sinf(i);
}
TOCK(cpu_sinf)
TICK(gpu_sinf)
para_for<<<16, 64>>>(
size, [arr = arr.data()] __device__(int i) { arr[i] = sinf(i); });
cudaError_t err = cudaDeviceSynchronize();
TOCK(gpu_sinf)
if (err != cudaSuccess) {
printf("Error:%s\n", cudaGetErrorName(err));
return 0;
}
}
结果:

可以看到,求正弦GPU是要快于CPU的,这里差距还不明显,一般来说速度是由数量级上的差距的
C++编程笔记(GPU并行编程-2)的更多相关文章
- 五 浅谈CPU 并行编程和 GPU 并行编程的区别
前言 CPU 的并行编程技术,也是高性能计算中的热点,也是今后要努力学习的方向.那么它和 GPU 并行编程有何区别呢? 本文将做出详细的对比,分析各自的特点,为将来深入学习 CPU 并行编程技术打下铺 ...
- 第五篇:浅谈CPU 并行编程和 GPU 并行编程的区别
前言 CPU 的并行编程技术,也是高性能计算中的热点,也是今后要努力学习的方向.那么它和 GPU 并行编程有何区别呢? 本文将做出详细的对比,分析各自的特点,为将来深入学习 CPU 并行编程技术打下铺 ...
- 三 GPU 并行编程的运算架构
前言 GPU 是如何实现并行的?它实现的方式较之 CPU 的多线程又有什么分别?本文将做一个较为细致的分析. GPU 并行计算架构 GPU 并行编程的核心在于线程,一个线程就是程序中的一个单一指令流, ...
- 第三篇:GPU 并行编程的运算架构
前言 GPU 是如何实现并行的?它实现的方式较之 CPU 的多线程又有什么分别? 本文将做一个较为细致的分析. GPU 并行计算架构 GPU 并行编程的核心在于线程,一个线程就是程序中的一个单一指令流 ...
- 四 GPU 并行编程的存储系统架构
前言 在用 CUDA 对 GPU 进行并行编程的过程中,除了需要对线程架构要有深刻的认识外,也需要对存储系统架构有深入的了解. 这两个部分是 GPU 编程中最为基础,也是最为重要的部分,需要花时间去理 ...
- 第四篇:GPU 并行编程的存储系统架构
前言 在用 CUDA 对 GPU 进行并行编程的过程中,除了需要对线程架构要有深刻的认识外,也需要对存储系统架构有深入的了解. 这两个部分是 GPU 编程中最为基础,也是最为重要的部分,需要花时间去理 ...
- 【并行计算-CUDA开发】GPU并行编程方法
转载自:http://blog.sina.com.cn/s/blog_a43b3cf2010157ph.html 编写利用GPU加速的并行程序有多种方法,归纳起来有三种: 1. 利用现有的G ...
- 大数据学习笔记3 - 并行编程模型MapReduce
分布式并行编程用于解决大规模数据的高效处理问题.分布式程序运行在大规模计算机集群上,集群中计算机并行执行大规模数据处理任务,从而获得海量计算能力. MapReduce是一种并行编程模型,用于大规模数据 ...
- C#并发编程之初识并行编程
写在前面 之前微信公众号里有一位叫sara的朋友建议我写一下Parallel的相关内容,因为手中商城的重构工作量较大,一时之间无法抽出时间.近日,这套系统已有阶段性成果,所以准备写一下Parallel ...
- GPU并行编程小结
http://peghoty.blog.163.com/blog/static/493464092013016113254852/ http://blog.csdn.net/augusdi/artic ...
随机推荐
- 【gRPC】C++异步服务端优化版,多服务接口样例
官方的C++异步服务端API样例可读性并不好,理解起来非常的费劲,各种状态机也并不明了,整个运行过程也容易读不懂,因此此处参考网上的博客进行了重写,以求顺利读懂. C++异步服务端实例,详细注释版 g ...
- 【学习笔记】RNN算法的pytorch实现
一些新理解 之前我有个疑惑,RNN的网络窗口,换句话说不也算是一个卷积核嘛?那所有的网络模型其实不都是一个东西吗?今天又听了一遍RNN,发现自己大错特错,还是没有学明白阿.因为RNN的窗口所包含的那一 ...
- 5_项目实战MyShop
一. 网上商城 1.1 商城类别 B2B 商家对商家 B2C 商家对客户 C2C 客户对客户 O2O 线上线下相结合 1.2 商城常见模块 后台常见功能模块 商品管理 包括后台商品库存管理, 上货, ...
- Centos7下的基本操作
本系统是在centos7下最小化安装的 文件操作相关 创建文件夹mkdir name //创建一个文件夹 创建文本touch test.txt //创建文本 删除文件夹rm -rf 文件名 //删除文 ...
- DophineSheduler上下游任务之间动态传参案例及易错点总结
作者简介 淡丹 数仓开发工程师 5年数仓开发经验,目前主要负责百得利MOBY新车业务 二手车业务及售后服务业务系统数仓建设 业务需求 在ETL任务之间调度时,我们有的时候会需要将上游的 ...
- 市面上erp软件那么多,为什么很多卖家选择定制erp?
为什么选择定制ERP?适合自己的才是最好的啊!就连头部ERP企业提供给用户的ERP系统,应该也没有不进行个性化定制的吧,匹配很重要!规模不同.行业不同.发展阶段不同.生产模式不同.管理理念不同,适用的 ...
- # 如何在Windows下运行Linux程序
如何在Windows下运行Linux程序 一.搭建 Linux 环境 1.1 安装 VMware Workstation https://www.aliyundrive.com/s/TvuMyFdTs ...
- abstract关键字的使用
1.abstract:抽象的 2.abstract可以用来修饰的结构:类.方法 3.abstract修饰类:抽象类 此类不能实例化 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全 ...
- HNOI2008GT考试
题目链接 考虑dp,f(i,j)表示做到了第i位(共n位),当前的后缀串与A1~Aj相匹配 接下来的方案数.转移的话枚举一个k=0~9表示这位选什么,如果选了以后,匹配的位置会改变到 j' ,j'可以 ...
- GitHub Pages 和 Jekyll 笔记
GitHub Pages 和 Jekyll 笔记 快速创建(使用默认的Jekyll引擎) 1. 新建仓库 新建一个空仓库, 名称为username.github.io, 其中 username 就是你 ...