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]);
}
}

其中allocatedeallocate是必须实现的

这里不用默认的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)的更多相关文章

  1. 五 浅谈CPU 并行编程和 GPU 并行编程的区别

    前言 CPU 的并行编程技术,也是高性能计算中的热点,也是今后要努力学习的方向.那么它和 GPU 并行编程有何区别呢? 本文将做出详细的对比,分析各自的特点,为将来深入学习 CPU 并行编程技术打下铺 ...

  2. 第五篇:浅谈CPU 并行编程和 GPU 并行编程的区别

    前言 CPU 的并行编程技术,也是高性能计算中的热点,也是今后要努力学习的方向.那么它和 GPU 并行编程有何区别呢? 本文将做出详细的对比,分析各自的特点,为将来深入学习 CPU 并行编程技术打下铺 ...

  3. 三 GPU 并行编程的运算架构

    前言 GPU 是如何实现并行的?它实现的方式较之 CPU 的多线程又有什么分别?本文将做一个较为细致的分析. GPU 并行计算架构 GPU 并行编程的核心在于线程,一个线程就是程序中的一个单一指令流, ...

  4. 第三篇:GPU 并行编程的运算架构

    前言 GPU 是如何实现并行的?它实现的方式较之 CPU 的多线程又有什么分别? 本文将做一个较为细致的分析. GPU 并行计算架构 GPU 并行编程的核心在于线程,一个线程就是程序中的一个单一指令流 ...

  5. 四 GPU 并行编程的存储系统架构

    前言 在用 CUDA 对 GPU 进行并行编程的过程中,除了需要对线程架构要有深刻的认识外,也需要对存储系统架构有深入的了解. 这两个部分是 GPU 编程中最为基础,也是最为重要的部分,需要花时间去理 ...

  6. 第四篇:GPU 并行编程的存储系统架构

    前言 在用 CUDA 对 GPU 进行并行编程的过程中,除了需要对线程架构要有深刻的认识外,也需要对存储系统架构有深入的了解. 这两个部分是 GPU 编程中最为基础,也是最为重要的部分,需要花时间去理 ...

  7. 【并行计算-CUDA开发】GPU并行编程方法

    转载自:http://blog.sina.com.cn/s/blog_a43b3cf2010157ph.html 编写利用GPU加速的并行程序有多种方法,归纳起来有三种: 1.      利用现有的G ...

  8. 大数据学习笔记3 - 并行编程模型MapReduce

    分布式并行编程用于解决大规模数据的高效处理问题.分布式程序运行在大规模计算机集群上,集群中计算机并行执行大规模数据处理任务,从而获得海量计算能力. MapReduce是一种并行编程模型,用于大规模数据 ...

  9. C#并发编程之初识并行编程

    写在前面 之前微信公众号里有一位叫sara的朋友建议我写一下Parallel的相关内容,因为手中商城的重构工作量较大,一时之间无法抽出时间.近日,这套系统已有阶段性成果,所以准备写一下Parallel ...

  10. GPU并行编程小结

    http://peghoty.blog.163.com/blog/static/493464092013016113254852/ http://blog.csdn.net/augusdi/artic ...

随机推荐

  1. Unity接入微信支付SDK 2022年版安卓篇

    最近1年转了UE开发,博客更新的比较少,技术栈宽了不少,以后有空尽量多更新,也方便总结记忆 Unity接入微信支付整个过程坑比较多,网上之前的教程要么比较老,要么比较零碎,只能东拼西凑摸索,跑通后还是 ...

  2. 【项目实战】Kaggle泰坦尼克号的幸存者预测

    前言 这是学习视频中留下来的一个作业,我决定根据大佬的步骤来一步一步完成整个项目,项目的下载地址如下:https://www.kaggle.com/c/titanic/data 大佬的传送门:http ...

  3. Deepin系统navicat15安装

    Deepin系统安装navicat15(已验证) 下载Navicat15 通过下面地址下载Navicat15,默认下载到桌面即可 $ https://download.navicat.com.cn/d ...

  4. C++ 自学笔记 new和delete(动态内存分配)

    动态内存分配 Dynamic memoey allocation C++使用new和delete 来申请和释放内存 new:先申请一个空间 int\Stash : 默认构造函数初始化对象 ~:析构函数 ...

  5. http和https分别是什么?

    http中文名:超文本传输协议英文名:Hyper Text Transfer Protocol解释:是一个简单的请求-响应协议,它通常运行在TCP之上.它指定了客户端可能发送给服务器什么样的消息以及得 ...

  6. python实验报告(第五周)

    一.实验目的和要求 学会使用字符串的常用操作方法和正确应用正则表达式. 二.实验环境 软件版本:Python 3.10 64_bit 三.实验过程 1.实例1:使用字符串拼接输出一个关于程序员的笑话 ...

  7. SSM项目环境快速搭建

    SSM项目的环境搭建 环境搭建的目标 工程创建 创建父工程 创建空 maven工程 xxx-parent 作为父工程 修改父工程中的 pom.xml <!--?xml version=" ...

  8. 🔥支持 Java 19 的轻量级应用开发框架,Solon v1.10.4 发布

    Java 轻量级应用开发框架.可用来快速开发 Java 应用项目,主框架仅 0.1 MB. 相对于 Spring Boot 和 Spring Cloud 的项目: 启动快 5 - 10 倍. (更快) ...

  9. 极客的浪漫「GitHub 热点速览 v.22.41」

    极客的浪漫,是怀旧复古的开源操作系统 SerenityOS 献上的情书:也是实用派用 AI 作画工具 novelai-bot 生成二次元女友.LxgwWenKai 用仿宋 / 楷体中文字体书写而成的那 ...

  10. HTML+CSS基础知识(2)选择器的使用、盒子模型的讲解、列表的使用

    文章目录 1.CSS基础知识 2.css样式 2.1.代码: 2.2 测试结果 3.CSS的语法 3.1 代码 4.块元素和行内元素 4.1 代码 4.2 测试结果 5.常用的选择器 5.1 代码块 ...