参加CUDA线上训练营·(二)cuda的c++编译

2023-10-30

目前c++流行的编译器有cmake,clang,qmake,xmake等,本文主要介绍如何在cmake和xmake中编译cuda。

xmake

简介

xmake是国人开发的一款编译器,官方链接如下:xmake官网。该编译器安装方便,上手快,支持c++,cuda,Qt,iOS等语言和项目的编译,我在进行简单的模块开发时喜欢用xmake快速生成项目以进行测试。

使用

xmake的安装过程此处略过,官方文档里很详细。使用xmake时只要一行指令就可以创建一个完整的空项目:

user@user-:~/桌面$ xmake create -P project -l cuda
create project ...
  [+]: xmake.lua
  [+]: src/main.cu
  [+]: .gitignore
create ok!

这是xmake自动生成的main.cu文件,可在内部修改


#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>

cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);

__global__ void addKernel(int *c, const int *a, const int *b)
{
    int i = threadIdx.x;
    c[i] = a[i] + b[i];
}

int main()
{
    const int arraySize = 5;
    const int a[arraySize] = {1, 2, 3, 4, 5};
    const int b[arraySize] = {10, 20, 30, 40, 50};
    int c[arraySize] = {0};

    // Add vectors in parallel.
    cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize);
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "addWithCuda failed!");
        return 1;
    }

    printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
           c[0], c[1], c[2], c[3], c[4]);

    // cudaDeviceReset must be called before exiting in order for profiling and
    // tracing tools such as Nsight and Visual Profiler to show complete traces.
    cudaStatus = cudaDeviceReset();
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "cudaDeviceReset failed!");
        return 1;
    }

    return 0;
}

// Helper function for using CUDA to add vectors in parallel.
cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size)
{
    int *dev_a = 0;
    int *dev_b = 0;
    int *dev_c = 0;
    cudaError_t cudaStatus;

    // Choose which GPU to run on, change this on a multi-GPU system.
    cudaStatus = cudaSetDevice(0);
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?");
        goto Error;
    }

    // Allocate GPU buffers for three vectors (two input, one output)    .
    cudaStatus = cudaMalloc((void **)&dev_c, size * sizeof(int));
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    cudaStatus = cudaMalloc((void **)&dev_a, size * sizeof(int));
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    cudaStatus = cudaMalloc((void **)&dev_b, size * sizeof(int));
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    // Copy input vectors from host memory to GPU buffers.
    cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    // Launch a kernel on the GPU with one thread for each element.
    addKernel<<<1, size>>>(dev_c, dev_a, dev_b);

    // Check for any errors launching the kernel
    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        goto Error;
    }

    // cudaDeviceSynchronize waits for the kernel to finish, and returns
    // any errors encountered during the launch.
    cudaStatus = cudaDeviceSynchronize();
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
        goto Error;
    }

    // Copy output vector from GPU buffer to host memory.
    cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost);
    if (cudaStatus != cudaSuccess)
    {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

Error:
    cudaFree(dev_c);
    cudaFree(dev_a);
    cudaFree(dev_b);

    return cudaStatus;
}

编译方面,进入project文件夹,使用以下指令运行:

user@user:~/桌面/$ cd project/
user@user:~/桌面/project$ xmake
checking for platform ... linux
checking for architecture ... x86_64
checking for Cuda SDK directory ... /usr/local/cuda
[ 25%]: compiling.release src/main.cu
[ 50%]: devlinking.release project_gpucode.cu.o
[ 50%]: linking.release project
[100%]: build ok!
user@user:~/桌面/project$ xmake run
{1,2,3,4,5} + {10,20,30,40,50} = {11,22,33,44,55}

总结

xmake使用较为简单,可以满足常规的使用要求,但该编译器毕竟不如cmake这么流行,在社区和使用的广度上仍然存在一些问题,因此个人建议仅用于小型的算法验证,至于大型项目还是考虑cmake。

cmake

版本差异

cmake作为使用最广泛的c++编译器之一,不再多做介绍,此处需要说明的是使用cmake编译cuda时需要注意版本问题。在早期版本中,cmake需要使用find_package 和 link_directories将cuda的文件和库链接到程序中(使用 CMake 构建跨平台 CUDA 应用程序),但在cmake3.10以后通过开启cuda编译选项,可以不再使用find cuda(findcuda文档)。

使用 CMake 构建跨平台 CUDA 应用程序

在这里插入图片描述
我有两台电脑,一台Ubuntu18,另一台Ubuntu20,以前遇到过相同的代码放到20上就会编译报错,后来排查的原因是18默认安装的cmake是3.10版本,而20默认的是3.16,正好处在新老分界线上,因此使用时需要注意。

检查cuda是否正常安装

由于cmake和cuda的安装都比较繁琐,有的时候编译报错也无法确定究竟是cuda的安装问题还是cmakelists的编写问题,因此建议先使用xmake生成一个简单的demo,如果能正常运行则大概率是cmakelists的问题,反之则需要检查cuda的安装。

示例

cmake版本基于3.23,注意:不同的cmake可能需要使用不同的指令,低版本编译可能报错。文件结构如下所示:

user@user:~/test/test/cuda$ tree -L 1
.
├── bin
├── build
├── CMakeLists.txt
├── cuda_alg.cu
├── cuda_alg.h
└── main.cpp

2 directories, 4 files

main.cpp

#include <iostream>
#include "cuda_alg.h"


int main()
{
    CudaTest cuda_test;
    cuda_test.run();
    
    return 0;
}

cuda_alg.h

#ifndef _CUDA_ALG_H_
#define _CUDA_ALG_H_

#include <iostream>
#include <stdio.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

class CudaTest
{
public:
    void run();
private:
};
#endif


cuda_alg.cu

#include "cuda_alg.h"


__global__ void helloWorldGPU(const int size)
{
    const int n = blockDim.x * blockIdx.x + threadIdx.x;
    if(n < size)
    {
        printf("hello world:%d\n", n);
    }
    
}


void CudaTest::run()
{
    
    helloWorldGPU<<<1, 8>>>(8);
    
    cudaDeviceSynchronize();
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(test LANGUAGES CXX CUDA)

find_package(CUDA REQUIRED)

cuda_add_executable (${PROJECT_NAME}
                main.cpp
                cuda_alg.cu )

运行结果

user@user:~/test/test/cuda/build$ ./test 
hello world:0
hello world:1
hello world:2
hello world:3
hello world:4
hello world:5
hello world:6
hello world:7
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

参加CUDA线上训练营·(二)cuda的c++编译 的相关文章

  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 根据属性的类型使用文本框或复选框

    如果我有这样的结构 public class Parent public string Name get set public List
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐

  • clock gate cell 时钟门控单元

    1 结构图 锁存器 与门 D触发器 latch或reg 用于同步使能信号 防止出现亚稳态和毛刺 与门 使能信号无效时 关断模块输入时钟 D触发器 简化的reg 2 为什么需要clk gate 模块不工作时 clk翻转浪费功耗 模块 reg相
  • rsync: mkstemp ... failed: Operation not permitted

    今天在整理文件时遇到了下面的错误 rsync mkstemp abc def txt dm1u5x failed Operation not permitted 1 说说我的情况 我的 abc 目录是一个独立的 mount point 只有
  • 【通览一百个大模型】FLAN(Google)

    通览一百个大模型 FLAN Google 作者 王嘉宁 本文章内容为原创 仓库链接 https github com wjn1996 LLMs NLP Algo 订阅专栏 大模型 NLP 算法 可获得博主多年积累的全部NLP 大模型和算法干
  • [NSSCTF 2nd]

    文章目录 NSSCTF 2nd MISC gift in qrcode WEB php签到 MyBox MyBox rev MyHurricane MyJS NSSCTF 2nd MISC gift in qrcode import qrc
  • 关于Realtek 8821ce wireless lan 802.11ac网络适配器无法使用

    关于网络适配器realtek 8821ce wireless lan 802 11ac无法使用的问题 提示 并不适用于所有出现该问题的电脑 本次针对的电脑是win10系统 其他系统并没有测试过 参考1 https blog csdn net
  • 【Shell牛客刷题系列】SHELL15 去掉不需要的单词:总结awk命令中的内置函数

    该系列是基于牛客Shell题库 针对具体题目进行查漏补缺 学习相应的命令 刷题链接 牛客题霸 Shell篇 该系列文章都放到专栏下 专栏链接为 专栏 Linux 欢迎关注专栏 本文知识预告 本文首先总结了awk命令中的各个内置函数的用法 然
  • 【VC】【全局修改windows系统环境变量】 实现和原理详解

    文章目录 导读 开发环境 实现 通过procexp打开1836进程的环境变量列表 修改注册表 手动 编码实现 广播WM SETTINGCHANGE消息 再次通过procexp打开1836进程的环境变量列表 也可以通过 系统属性 gt 环境变
  • 数据和C学习

    第三章 数据和C 3 1 示例程序 include
  • Linux:冯诺伊曼体系结构

    文章目录 冯诺依曼 主板 显卡 外设 数据流的流向 操作系统OS 系统调用接口和库函数 参考 全文约 1600 字 阅读时长预计 5分钟 冯诺依曼 我们所认识的计算机 都是有一个个的硬件组件组成 冯 诺依曼结构的核心思想 一 确定了 计算机
  • Nginx教程(小白必看,看了必会,不看血亏),

    Notice 测试请打开浏览器禁止缓存 Notice 再使用前 请打开浏览器 F12 然后网络 然后点禁用缓存 避免nginx配置后磁盘缓存的情况 而且 请确认host没问题 备注 你本地设置的host对服务器反向代理后的就没用了 一 介绍
  • 还没毕业,我就进了HR的黑名单!

    今天小红书上的一则热搜 原文求助如下 马赛克的地方是之前的实习单位 这封邮件是发到我的工作邮箱 工作邮箱写在了简历里 因为最近一直在投简历 所以给我发邮箱的人应该是hr 不是什么恶作剧 现在正在疯狂找工作 所以看到这个邮件太害怕了 实在是不
  • idea无法创建servlet

    问题引入 new里面没有servlet项目 自己创建后也无法继承HttpServlet类 整篇代码爆红参考如下博客 IntelliJ IDEA关于 cannot resolve symbol servlet 的解决 进阶中的非主流坛子的博客
  • 2020美赛C题翻译

    翻译 问题C 数据的财富 在其创建的在线市场中 亚马逊为客户提供了对购买进行评分和评价的机会 个人评级 称为 星级 使购买者可以使用1 低评级 低满意度 到5 高评级 高满意度 的等级来表示他们对产品的满意度 此外 客户可以提交基于文本的消
  • JAVA基础之理解JNI原理及应用

    java 以其跨平台的特性深受人们喜爱 而又正由于它的跨平台的目的 使得它和本地机器的各种内部联系变得很少 约束了它的功能 解决JAVA对本地操作的一种方法就是JNI JAVA通过JNI调用本地方法 而本地方法是以库文件的形式存放的 在WI
  • Java 变量

    局部变量 局部变量声明在方法 构造方法或者语句块中 局部变量在方法 构造方法 或者语句块被执行的时候创建 当它们执行完成后 变量将会被销毁 访问修饰符不能用于局部变量 局部变量只在声明它的方法 构造方法或者语句块中可见 局部变量是在栈上分配
  • uml类图浅录

    uml类图 UML中类图的绘制 单个类图的绘制 类图中的成员访问属性 UML类图中类与类的几种关系 关联 代码示例解释 UML类图表示 多重性说明 依赖 代码示例解释 uml类图表示 继承 示例代码解释 UML类图表示 实现 示例代码解释
  • 加密与解密:一个简单的C语言示例

    写在前面 做大一年级的导生 碰巧一个同学问了一个C语言程序设计的题目 说是怎么都弄不对 我看了看 正好也是三年前我碰到的题目 仿佛还噙着旧日时光的泪痕 特此将题目与我的解法奉上 以祭奠那段逝去的时光 1 问题是什么 1 使用要求的方法加密
  • 苹果系统自带的计算机怎么恢复出厂设置方法,苹果电脑Mac怎么恢复出厂系统?Mac恢复出厂系统操作方法...

    Mac和Windows在恢复出厂设置这方面有着异曲同工的操作 其实mac和macbook 系列重装系统或者叫恢复出厂设置 都是一样的步骤 一样的概念 下面来看下具体重装系统 恢复出厂设置 步骤和注意事项 Mac恢复出厂系统操作方法 一 重启
  • android状态栏透明!6年菜鸟开发面试字节跳动安卓研发岗,年薪50W

    本专栏专注分享大型Bat面试知识 后续会持续更新 喜欢的话麻烦点击一个关注 面试官 组件化如何实现 组件化与插件化的差别在哪里 该怎么选型 心理分析 面试官从架构层次 了解求职者是否用过 模块化 组件化 和插件化 在过去经验有没有运用过这些
  • 参加CUDA线上训练营·(二)cuda的c++编译

    目前c 流行的编译器有cmake clang qmake xmake等 本文主要介绍如何在cmake和xmake中编译cuda xmake 简介 xmake是国人开发的一款编译器 官方链接如下 xmake官网 该编译器安装方便 上手快 支持