cuda程序编译流程

news2024/12/23 18:33:19

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和B
    randomMatrixInit(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.coloradmin.cn/o/2178293.html

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

相关文章

Vivado - JTAG to AXI Master (GPIO、IIC、HLS_IP)

目录 1. 简介 2. JTAG to AXI Master 2.1 添加 IP Core 2.2 基本TCL命令 2.2.1 复位 JTAG-to-AXI Master 2.2.2 创建并运行写入传输事务 2.2.3 创建并运行读取传输事务 2.2.4 命令列表 2.3 帮助信息 2.4 创建TCL读写程序 2.4.1 Read proc 2.4.2 Write proc 2.4.3 …

嵌入式学习--LinuxDay03

嵌入式学习--LinuxDay03 shell脚本 1.1功能性语句 1.1.1说明性语句 1.1.2功能性语句 1&#xff09;read 2&#xff09;expr 3) test a)字符串 b)整数的测试 c)文件属性的测试 1.2结构性语句 1.2.1if语句 1.2.2case语句 1.2.3for循环 1.2.4while循环 1.2.5循环控制语句 shell脚本…

心觉:运用吸引力法则和开发潜意识的核心中的核心是什么?

吸引力法则的核心在于 思想的力量 和 频率的匹配。你所思考和感受的会吸引与你频率相匹配的事物和经历到你的生活中。具体来说&#xff1a; 明确意图和目标&#xff1a;清晰地知道你想要什么&#xff0c;并且用详细的方式描述它。这可以是通过写下目标、制作愿景板&#xff08;…

rocky9.2实现lvs(DR模式)+keepalived实现高可用的案例详解(双机热备、lvs负载均衡、对后端服务器健康检查)

文章目录 [TOC] 前言lvs(DR模式)的工作原理环境实现过程一、lvs1配置二、lvs2配置web1配置web2配置结果验证 总结 前言 想必能搜到这个也不是来看知识点的&#xff0c;这里就简单描述一下lvs的dr模式的工作原理&#xff0c;其他的就不过多阐述了,直接看操作步骤就好&#xff0…

rabbitMQ 简单使用

安装 rabbitMQ 下载地址&#xff1a;rabbitmq-3.12.0 安装 windows rabbitMQ 需要的命令 进入 rabbitMQ 的 sbin 目录后 cmd &#xff08;需要管理员权限&#xff09; rabbitmq-plugins.bat enable rabbitmq_management随后重启 rabbitMQ #关闭服务 net stop rabbitmq #开…

【机器学习(八)】分类和回归任务-因子分解机(Factorization Machines,FM)算法-Sentosa_DSML社区版

文章目录 一、算法概念二、算法原理&#xff08;一&#xff09; FM表达式&#xff08;二&#xff09;时间复杂度&#xff08;三&#xff09;回归和分类 三、算法优缺点&#xff08;一&#xff09;优点&#xff08;二&#xff09;缺点 四、FM分类任务实现对比&#xff08;一&…

YOLOV8在清微智能芯片的部署与实现(一)

现在以YOLOV8 为例&#xff0c;进行演示 文章目录 1. YOLOV8浮点模型训练1.1 准备数据集1.1.1 下载业务数据集1.1.2 下载开源数据集1.1.3 自定义数据集1.1.4 将数据转换为yolo训练数据格式 1.2 yolov8项目准备1.3 训练模型 2. YOLOV8浮点模型推理2.1 模型推理2.2 模型val.py评…

纯CSS实现有趣emoji切换开关

这是一个纯CSS创建的动画切换开关&#xff0c;它不仅能够在视觉上吸引用户&#xff0c;还能通过交互提供即时反馈。本文将解析源码的核心实现逻辑&#xff0c;这个项目的核心是使用CSS变量、3D变换和过渡效果来实现一个动态的、响应式的用户界面元素。 关键技术点 CSS变量&am…

[Python学习日记-31] Python 中的函数

[Python学习日记-31] Python 中的函数 简介 语法定义 函数的参数 简介 引子&#xff1a; 你是某公司的一个高级程序员&#xff0c;现在老板让你写一个监控程序&#xff0c;需要24小时全年无休的监控公司网站服务器的系统状况&#xff0c;当 CPU、Memory、Disk 等指标的使用…

基于SpringBoot+Vue+MySQL的体育商城系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着互联网的飞速发展&#xff0c;电子商务已成为人们日常生活中不可或缺的一部分。体育用品市场作为其中的一个重要分支&#xff0c;也逐渐向线上转移。基于SpringBootVueMySQL的体育商城系统应运而生&#xff0c;旨在通过构建…

如何使用ssm实现基于Java的高校物业工程报修系统

TOC ssm736基于Java的高校物业工程报修系统jsp 绪论 1.1研究背景与意义 信息化管理模式是将行业中的工作流程由人工服务&#xff0c;逐渐转换为使用计算机技术的信息化管理服务。这种管理模式发展迅速&#xff0c;使用起来非常简单容易&#xff0c;用户甚至不用掌握相关的专…

一行命令将Cmder添加到系统右键菜单中----配置环境

第一步&#xff0c;去官网下载一个简版的文件 ** 第二步&#xff0c;将下载的文件解压后如图&#xff0c;找到Cmder.exe右键以管理员身份运行 第三步&#xff0c;在窗口输入cmder /register all然后回车 第四步&#xff0c;OK!不管在哪里都可以使用了&#xff0c;直接右键即可

vscode环境迁移

关注B站可以观看更多实战教学视频&#xff1a;hallo128的个人空间 vscode环境迁移 Setting 即可打开settings.json {"python.pythonPath": "/Users/apple/opt/anaconda3/bin/python","cmake.cmakePath": "/usr/local/bin/cmake",&qu…

[c++高阶]模版进阶

1.前言 在我们学习c的时候&#xff0c;常常会遇见要使用函数重载的情况。而当使用函数重载时&#xff0c;通常会使得我们编写很多重复的代码&#xff0c;这样就显得非常臃肿&#xff0c;并且效率非常的低下。 重载的函数仅仅只是类型不同&#xff0c;代码的复用率比较低&#x…

浮点数的这些特性你了解吗

问题1:下面的代码&#xff0c;输出结果是什么&#xff1a; public class CaclTest{public void test1(){float f 1.0F / 0.0F;System.out.println("f:" f)}public static void main(String[] args){CaclTest ct new CaclTest();ct.test1();}} A. 运行抛出异常:j…

7.数据结构与算法-循环链表

如果经常对首位元素进行操作&#xff0c;用尾元素更方便更快捷 两个循环链表合并

信息安全工程师(21)安全协议

前言 安全协议是建立在密码体制基础上的一种交互通信协议&#xff0c;它运用密码算法和协议逻辑来实现认证、密钥分配、数据机密性、完整性和抗否认性等安全目标。 一、定义与目的 安全协议旨在确保网络环境中信息交换的安全性&#xff0c;通过密码技术和协议逻辑来保护数据的机…

第八届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)

一.题目分析 &#xff08;1&#xff09;.题目 &#xff08;2&#xff09;.题目分析 1.按键功能分析----过程控制 a. 选择按键按下的个数和目标层数&#xff08;每个按键都要在一秒之内按下&#xff0c;否则就结束&#xff09; b. 当升降机到达目标平台&#xff0c;LED灯熄灭 c.…

负载均衡(Load Balancing)是一种计算机技术,用于在网络应用中分配工作负载,以优化资源使用、最大化吞吐量、减少响应时间以及避免过载。

负载均衡&#xff08;Load Balancing&#xff09;是一种计算机技术&#xff0c;用于在网络应用中分配工作负载&#xff0c;以优化资源使用、最大化吞吐量、减少响应时间以及避免过载。通过将任务均匀地分布在多个组件上&#xff0c;如服务器、网络链接、CPU、硬盘等&#xff0c…

【AG 创新工坊】探索存内计算的未来,共话 AGI 时代

目录 ⚛️1. 会议详情 ☪️2. 会议回顾 ♋2.1 多模态时代&#xff0c;存内计算架构的应用与发展 ♏2.2 分布式环境下深度学习任务的高效可靠执行研究 ♐2.3 IGZO在后道单片三维集成中的机遇与挑战 ♑2.4 witin-nn:神经网络算法模型在存内开发板上的应用开发 ♉2.5 茶歇交…