cuda程序编译流程

cuda程序编译流程

本文以cuda example的matrixMul矩阵乘法为例说明cuda程序的编译流程。

1. 源代码 .cu 文件

matrixMul示例中,源代码文件 matrixMul.cu 是典型的CUDA程序,包含以下部分:

流程图

在这里插入图片描述

  • 主机代码(Host Code):运行在CPU上的代码,用于数据准备、调用CUDA内核(kernel)等。
  • 设备代码(Device Code):运行在GPU上的CUDA内核,负责矩阵乘法计算。
#include <stdio.h>
#include <cuda_runtime.h>// CUDA内核:用于执行矩阵乘法
__global__ void MatrixMulKernel(float* C, const float* A, const float* B, int width) {int x = blockIdx.x * blockDim.x + threadIdx.x;  // 矩阵的列索引int y = blockIdx.y * blockDim.y + threadIdx.y;  // 矩阵的行索引if (x < width && y < width) {float sum = 0;for (int i = 0; i < width; ++i) {sum += A[y * width + i] * B[i * width + x];  // A的行与B的列对应相乘累加}C[y * width + x] = sum;  // 结果存储在C矩阵中}
}void randomMatrixInit(float* mat, int size) {for (int i = 0; i < size; ++i) {mat[i] = rand() % 10;  // 随机初始化矩阵中的每个元素}
}int main() {int width = 16;  // 矩阵的宽度(假设矩阵是正方形,大小为 width * width)int size = width * width;  // 矩阵的总元素个数// 分配主机内存float* h_A = (float*)malloc(size * sizeof(float));float* h_B = (float*)malloc(size * sizeof(float));float* h_C = (float*)malloc(size * sizeof(float));// 初始化矩阵A和BrandomMatrixInit(h_A, size);randomMatrixInit(h_B, size);// 分配设备内存float* d_A;float* d_B;float* d_C;cudaMalloc((void**)&d_A, size * sizeof(float));cudaMalloc((void**)&d_B, size * sizeof(float));cudaMalloc((void**)&d_C, size * sizeof(float));// 将主机内存中的数据拷贝到设备内存cudaMemcpy(d_A, h_A, size * sizeof(float), cudaMemcpyHostToDevice);cudaMemcpy(d_B, h_B, size * sizeof(float), cudaMemcpyHostToDevice);// 定义CUDA网格和块大小int blockSize = 16;  // 每个线程块中的线程数(16 x 16 的线程块)dim3 threadsPerBlock(blockSize, blockSize);dim3 numBlocks((width + blockSize - 1) / blockSize, (width + blockSize - 1) / blockSize);// 调用CUDA内核进行矩阵乘法运算MatrixMulKernel<<<numBlocks, threadsPerBlock>>>(d_C, d_A, d_B, width);// 将结果从设备内存拷贝回主机内存cudaMemcpy(h_C, d_C, size * sizeof(float), cudaMemcpyDeviceToHost);// 输出结果(可选)printf("Matrix A:\n");for (int i = 0; i < size; i++) {printf("%f ", h_A[i]);if ((i + 1) % width == 0) printf("\n");}printf("\nMatrix B:\n");for (int i = 0; i < size; i++) {printf("%f ", h_B[i]);if ((i + 1) % width == 0) printf("\n");}printf("\nMatrix C (Result):\n");for (int i = 0; i < size; i++) {printf("%f ", h_C[i]);if ((i + 1) % width == 0) printf("\n");}// 释放设备内存cudaFree(d_A);cudaFree(d_B);cudaFree(d_C);// 释放主机内存free(h_A);free(h_B);free(h_C);return 0;
}

2. C++ 预处理器

编译的第一步是C++预处理器,它处理宏定义、头文件包含以及代码中的条件编译部分。在此阶段,.cu文件会被预处理,生成中间文件 .cpp.i

3. CUDArtfe 编译步骤(C++ 和 CUDA 编译器)

a.主机代码路径(左侧)
  1. C++ 预处理器:处理.cu文件的主机部分,生成 .cpp4.ii 文件。
  2. CUDA 前端编译器 cudafe++:将预处理后的 .cpp4.ii 文件转换为 .cudafe1.cpp 文件。这个文件包含主机代码和设备代码的占位符。
  3. C++ 编译器:处理 .cudafe1.cpp 文件,生成主机端的 .o.obj 文件。这是CPU可执行的部分。
b.设备代码路径(右侧)

设备代码的编译流程比主机代码复杂,详细流程如下:

  1. C++ 预处理器:CUDA源代码中的设备代码被提取出来,并进行预处理,生成 .cpp1.ii 文件。这个文件是设备代码的初步处理结果。
  2. CUDA 前端编译器 cudafe:cudafe 将 .cpp1.ii 转换为 .cudafe1.gpu,这是设备端的中间表示文件,它的主要作用是处理CUDA设备代码的结构,提取 __global____device____host__ 修饰的函数,并将这些代码转换为适合进一步编译的中间形式。
  3. C 编译器预处理:对 .cudafe1.gpu 进行C预处理,生成 .cpp2.i 文件.在这个步骤中,设备代码再次经过C编译器的预处理器。这是为了进一步处理包含的头文件、宏定义等,并对 cudafe1.gpu 文件中的内容进行进一步的C语言级别的预处理。
  4. CUDA 前端编译器 cudafe:再次编译,生成 .cudafe2.gpu 文件,准备进一步转换为GPU代码。在这一步,cudafe 再次处理设备代码,分析C语言的结构,并将 .cpp2.i 文件中的设备代码转换为 cudafe2.gpu 文件。这是准备进行PTX代码生成的关键一步,它将设备代码进一步转化为中间表示,准备进入GPU架构相关的编译步骤。
  5. C 编译器预处理:将 .cudafe2.gpu 再次预处理,生成 .cpp3.i 文件。
  6. CUDA 编译器 cicc:将 .cpp3.i 文件编译为 PTX(并行线程执行)中间代码,输出 .ptx 文件。cicc 是CUDA编译器的核心组件之一,它负责将设备代码编译为PTX(Parallel Thread Execution)代码。PTX是NVIDIA的中间代码表示,类似于汇编语言,它是高层次的机器码,独立于具体的GPU硬件架构。
  7. PTX 汇编器 ptxas:将 .ptx 文件转化为设备可执行的 .cubin 文件。这是最终的设备二进制文件,GPU可以直接执行这个文件。

4. 生成胖二进制文件 fatbinary

通过 fatbinary 工具,多个 .cubin 文件被打包成 .fatbin 文件。这是“胖二进制”文件,支持不同架构的GPU设备。

5. 生成 .fatbin.c 文件

生成的 fatbin 文件会被转换为 .fatbin.c 文件,这是C语言代码文件,包含了设备代码的二进制部分,最终将和主机代码一起被编译。

6. 最终链接

最后,主机端的 .o 文件和设备端的 .fatbin.c 文件通过标准C/C++编译器(如 gccg++)进行链接。这个过程会将主机代码和设备代码一起打包成最终的可执行文件。

编译链接全过程

在这里插入图片描述


Ref

  1. https://blog.csdn.net/dark5669/article/details/53869631
  2. https://www.zhangty15226.com/2023/11/25/NVCC%E7%BC%96%E8%AF%91%E6%B5%81%E7%A8%8B/
  3. https://blog.csdn.net/fb_help/article/details/80462853
  4. https://cloud.baidu.com/article/3224884
  5. https://findhao.net/easycoding/2039
  6. https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html
  7. https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html
  8. https://docs.nvidia.com/cuda/cuda-runtime-api/index.html
  9. https://docs.nvidia.com/cuda/cuda-driver-api/index.html
  10. https://developer.nvidia.com/cuda-examplehttps://developer.nvidia.com/gpu-computing-sdk

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1550574.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

GNSS定位中自适应调整电离层延迟参数过程噪声的方法

文章目录 前言一、非差非组合PPP模型二、电离层功率谱密度计算三、具体实现方法3.1 不平滑3.2 三阶多项式平滑 参考文献 前言 GNSS定位中不少技术手段如PPP和长基线RTK需要将电离层延迟作为参数估计&#xff0c;电离层延迟的变化通常被描述为随机游走过程&#xff0c;而功率谱密…

1.2.1 计算机网络分层结构(上)

体系结构可分层使得不同的层次承担不同的功能。 知识点&#xff1a; 1.不同类型的节点&#xff0c;实现的功能层次可能不一样。 2.分层结构的设计并不唯一&#xff0c;可以根据实际需求增加或减少层次。 3.一个功能可以放在不同的层次反复出现。 根据分层结构不同可以分为&…

CORE MVC 过滤器 (筛选器)《2》 TypeFilter、ServiceFilter

TypeFilter、ServiceFilter ServiceFilter vs TypeFilter ServiceFilter和TypeFilter都实现了IFilterFactory ServiceFilter需要对自定义的Filter进行注册&#xff0c;TypeFilter不需要 ServiceFilter的Filter生命周期源自于您如何注册&#xff08;全局、区域&#xff09;&…

推荐4款2024年热门的PDF转ppt工具

有时候&#xff0c;我们为了方便&#xff0c;需要将PDF里面的内容直接转换的PPT的格式&#xff0c;既方便自己演示和讲解&#xff0c;也让我们可以更加灵活的进行文件的编辑和修改。如果大家不知道要如何进行操作的话&#xff0c;我可以为大家推荐几个比窘方便实用的PDF转换工具…

STM32LL库之printf函数重定向

1. 加入以下代码 int fputc(int ch,FILE *f) {LL_USART_TransmitData8(USART1,ch);while(!LL_USART_IsActiveFlag_TXE(USART1));//需要等待发送完成return(ch); }记得添加 stdio.h 头文件 2. 在MDK中勾选&#xff1a;Use MicroLIB

swiper+fixed的错误,splice函数的使用,提取年月日substring

做项目时的一些问题 swiperfixedsplice函数的使用重点在 alldata.splice(0, alldata.length, ...response.data.data);splicealldata.splice(0, alldata.length, ...response.data.data) 这行代码的功能为什么不直接赋值 提取年月日 substring swiperfixed 项目中的一个错误&a…

【人人都是P8程序员】Cursor 使用的十大技巧

Cursor 使用的十大技巧 总是在一个空的文件夹中创建一个新的项目 表述需求时尽量明确但谨慎 让Cursor从项目一开始就写README文档&#xff0c;让其记录清楚产品功能、实现技术栈等等&#xff0c;并在完成关键步骤后对README文档做及时的更新&#xff0c;第二天继续完成项目时…

npj Climate and Atmospheric Science I 新疆生地所陈亚宁研究员团队孙帆博士后发表最新研究进展

题目&#xff1a;The dominant warming season shifted from winter to spring in the arid region of Northwest China 主导中国西北干旱区升温的季节已从冬季转变为春季 期刊&#xff1a;npj Climate and Atmospheric Science IF及分区&#xff1a;实时IF/JCR分区/中科院分…

【Linux】Docker下载与使用-nginx

目录 一、Docker介绍 二、Docker结构 三、下载Daocker 1. 在linux上下载docker&#xff0c;执行以下命令即可&#xff1a; 2. 开启docker 3. 执行以下操作并进行使用 四、在Docker上安装nginx 一、Docker介绍 Docker&#xff1a;是给予Go语言实现的开源项…

召回12 曝光过滤 Bloom Filter

在推荐系统中&#xff0c;如果用户看过某个物品&#xff0c;就不再把物品推荐给这个用户。小红书、抖音都这样做曝光过滤&#xff0c;原因是实验表明重复曝光同一个物品会损害用户体验。但也不是所有推荐系统都有曝光过滤&#xff0c;像 YouTube 这样的长视频就没有曝光过滤&am…

ASR-01语音模块+C8T6实现语音控制LED

不说废话&#xff0c;简单直接&#xff0c;上教程&#xff0c;包会的&#xff0c;看不会&#xff0c;后台私我 一、接线图 STM32F103C8T6 ASR-01OLED屏PA10(RX接收串口)TX&#xff08;发送串口&#xff09;PB8SCL PB9 SDAVCCVCCGNDGND 二、天问软件Block图形编程 大家不要问…

Grafana链接iframe嵌入Web前端一直跳登录页面的问题记录

概述 公司有个项目使用到Grafana作为监控界面,因为项目方的环境极其复杂,仅物理隔离的环境就有三四个,而且每个都得部署项目,今天在某个环境测试,查看界面遇到一个比较奇怪的Grafana问题,后面针对该问题进行跟踪分析并解决,故而博文记录,用于备忘。 问题 登录项目We…

fastadmin 搜索提交重置按钮文本修改

默认 修改require-backend.min.js文件 效果 当然最好还是去需修改lang文件 效果 如果修改没生效记得清楚一下缓存&#xff0c;再刷新 完结 赠人玫瑰&#xff0c;手有余香&#xff01;如果文章内容对你有所帮助&#xff0c;请不要吝啬你的点赞评论和关注&#xff0c;你…

Tair简介

概述 Tair是淘宝团队开源的高可用分布式KV存储引擎&#xff0c;采用服务端自动负载均衡方式&#xff0c;使客户端逻辑简单。Tair&#xff0c;即TaoBao Pair缩写&#xff0c;Pair表示一对、一双等意思&#xff0c;即Key-Value数据对。 Tair分为持久化和非持久化两种方式。非持…

【Linux学习】【Ubuntu入门】2-1 Linux系统下运行C语言输出hello word

1.双击打开VMware软件&#xff0c;点击开启此虚拟机后&#xff0c;等待点击头像输入密码进入 2.“CtrlAltt”调出命令行终端&#xff0c;输入命令sudo apt-get install vim安装vim&#xff0c;输入命令sudo apt-get install gcc安装gcc 3.输入命令vi hello.c进入C语言编写环境&…

【D3.js in Action 3 精译_025】3.4 让 D3 数据适应屏幕(中)—— 线性比例尺的用法

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可…

[Python数据分析]最通俗入门Kmeans聚类分析,可视化展示附代码。

什么是k-means分析?【头条@William数据分析,看原版】 想象一下,你有一堆五颜六色的糖果,你想把它们按照颜色分成几堆。k-means分析就是这么一个自动分类的过程。它会根据糖果的颜色特征,把它们分成若干个组,每个组里的糖果颜色都比较相似。 更专业一点说,k-means分析是…

【C++并发入门】摄像头帧率计算和多线程相机读取(上):并发基础概念和代码实现

前言 高帧率摄像头往往应用在很多opencv项目中&#xff0c;今天就来通过简单计算摄像头帧率&#xff0c;抛出一个单线程读取摄像头会遇到的问题&#xff0c;同时提出一种解决方案&#xff0c;使用多线程对摄像头进行读取。同时本文介绍了线程入门的基础知识&#xff0c;讲解了…

【muduo源码分析】「阻塞」「非阻塞」「同步」「异步」

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 引言何为「muduo库」安装muduo库阻塞、非阻塞、同步、异步数据准备数据准备 引言 从本篇博客开始&#xff0c;我会陆续发表muduo库源码分析的相关文章。感谢大家的持续关注&#xff01;&#xff01;…

9.29总结

这星期学了概率和组合数学 这是我觉得的一个有趣的题目&#xff0c;每个人身上都有n-1根绳子&#xff0c;如果组不成稳定三角&#xff0c;那么肯定有两个人相邻两根绳子颜色不一样&#xff0c;那么每两个这样的人就会贡献一个不稳定三角形&#xff0c;所以只要所有三角形减去每…