ubuntu22.04+cuda11.5+gcc11.4第一个cuda程序示例

news2025/2/21 12:38:20

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

VisualStudio 2019是微软的集成开发环境(IDE),通常在Windows操作系统上使用。然而,并不直接支持在Linux上安装。如果想在Ubuntu上进行开发,可以考虑以下几个选项:
使用替代的IDE或文本编辑器: Ubuntu上有许多适用于C++等编程语言的开发工具,比如

Visual Studio Code、 Code.:Blocks、 Eclipse等。

使用虚拟机或容器: 如果你非常需要使用Visual Studio 2019,可以在Ubuntu上安装虚拟机软件(比如VirtualBox) 或容器平台(比如Docker) ,然后在虚拟机或容器中运行Windows,再在其中安装Visual Studio 2019。

使用Wine: Wine是一款允许在Linux上运行Windows应用程序的兼容层。你可以尝试使用Wine来安装和运行Visual Studio 2019,但请注意,并不是所有Windows应用程序都能在Wine下正常工作作。

使用双系统: 如果你需要长期在Linux上开发,但又需要使用VisualStudio 2019,可以考虑在计算机上设置双系统,一边运行Ubuntu,一边运行Windows

使用nano 文本编辑器创建文件,然后在终端中进行运行代码

在这里插入图片描述

gcc cuda example.cu -o cuda example/usr/bin/ld:cuda_example.cu: file format not recognized; treating as linker script/usr/bin/ld:cuda example.cu:5: syntax errorcollecto: error:ld returned i exit status

类似于上述错误信息,说明使用
~gcc尝试编译CUDA代码文件cuda_example.cu’,

~gcc无法直接编译CUDA代码。
CUDA代码需要使用NVIDIA的nvcc~编译器进行编译,因为它包含了CUDA特定的语法和功能。
编译运行CUDA代码,您需要使用NVIDIA的~nvce”编译器,而不是gcc”。

利用nvcc编译运行代码的步骤

示例代码如下

//本示例演示了如何使用 OpenMP API 为多个 GPU 编写应用程序
#include <iostream>
#include <omp.h>
#include <stdio.h>  // 使用 stdio 函数,因为 C++ 流不一定是线程安全的
#define checkCudaErrors(err) __checkCudaErrors(err, __FILE__, __LINE__)

inline void __checkCudaErrors(cudaError_t err, const char *file, int line) {
    if (err != cudaSuccess) {
        std::cerr << "CUDA error at " << file << ":" << line << " - " << cudaGetErrorString(err) << std::endl;
        exit(EXIT_FAILURE);
    }
}

using namespace std;

//一个简单的kernel,只需将每个数组元素递增 b
__global__ void kernelAddConstant(int *g_a, const int b)
{
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    g_a[idx] += b;
}

//用于检查每个数组元素是否被设置为其索引加上 b
int correctResult(int *data, const int n, const int b)
{
    for (int i = 0; i < n; i++)
        if (data[i] != i + b)
            return 0;

    return 1;
}
int main(int argc, char *argv[])
{
    int num_gpus = 0;   // CUDA GPU 数量

    printf("%s Starting...\n\n", argv[0]);

    /
   //确定支持 CUDA 的 GPU 数量
    cudaGetDeviceCount(&num_gpus);

    if (num_gpus < 1)
    {
        printf("no CUDA capable devices were detected\n");
        return 1;
    }

    /
    //显示 CPU 和 GPU 配置
    printf("number of host CPUs:\t%d\n", omp_get_num_procs());
    printf("number of CUDA devices:\t%d\n", num_gpus);

    for (int i = 0; i < num_gpus; i++)
    {
        cudaDeviceProp dprop;
        cudaGetDeviceProperties(&dprop, i);
        printf("   %d: %s\n", i, dprop.name);
    }
    printf("---------------------------\n");

    /
    // initialize data
    //
    unsigned int n = num_gpus * 8192;
    unsigned int nbytes = n * sizeof(int);
    int *a = 0;     // // 指向 CPU 上数据的指针
    int b = 3;      // 数组递增的值
    a = (int *)malloc(nbytes);

    if (0 == a)
    {
        printf("couldn't allocate CPU memory\n");
        return 1;
    }

    for (unsigned int i = 0; i < n; i++)
        a[i] = i;


    
// 运行与 CUDA 设备数量相同的 CPU 线程
    //每个 CPU 线程控制不同的设备,处理各自的数据部分。 
    // 使用的 CPU 线程数量有可能多于 CUDA 设备的数量,在这种情况下,多个 CPU 线程将在同一设备上分配资源并启动内核。
    // 例如,尝试 omp_set_num_threads(2 * num_gpus); 
    // 请注意,在 "omparallel "作用域内声明的所有变量都是 是每个 CPU 线程的局部变量
    //
    omp_set_num_threads(num_gpus);  //创建与 CUDA 设备数量相同的 CPU 线程
    //omp_set_num_threads(2*num_gpus);// 创建的 CPU 线程数量是 CUDA 设备数量的两倍
    #pragma omp parallel
    {
        unsigned int cpu_thread_id = omp_get_thread_num();
        unsigned int num_cpu_threads = omp_get_num_threads();

      
        int gpu_id = -1;
        checkCudaErrors(cudaSetDevice(cpu_thread_id % num_gpus));   
        checkCudaErrors(cudaGetDevice(&gpu_id));
        printf("CPU thread %d (of %d) uses CUDA device %d\n", cpu_thread_id, num_cpu_threads, gpu_id);

        int *d_a = 0; 
        int *sub_a = a + cpu_thread_id * n / num_cpu_threads;  
        unsigned int nbytes_per_kernel = nbytes / num_cpu_threads;
        dim3 gpu_threads(128);  // 128 threads per block
        dim3 gpu_blocks(n / (gpu_threads.x * num_cpu_threads));

        checkCudaErrors(cudaMalloc((void **)&d_a, nbytes_per_kernel));
        checkCudaErrors(cudaMemset(d_a, 0, nbytes_per_kernel));
        checkCudaErrors(cudaMemcpy(d_a, sub_a, nbytes_per_kernel, cudaMemcpyHostToDevice));
        kernelAddConstant<<<gpu_blocks, gpu_threads>>>(d_a, b);

         checkCudaErrors(cudaMemcpy(sub_a, d_a, nbytes_per_kernel, cudaMemcpyDeviceToHost));
        checkCudaErrors(cudaFree(d_a));
    }
    printf("---------------------------\n");

    if (cudaSuccess != cudaGetLastError())
        printf("%s\n", cudaGetErrorString(cudaGetLastError()));
    
    // check the result
    //
    bool bResult = correctResult(a, n, b);

    if (a)
        free(a); // free CPU memory

    exit(bResult ? EXIT_SUCCESS : EXIT_FAILURE);
}

  1. 打开终端(快捷键,ctrl+alt+t)
  2. 进入CUDA代码文件所在的目录,即 ‘/home/lcr/try’
cd /home/lcr/try

3.使用nvcc编译CUDA代码文件,并生成可执行文件。运行以下命令:

nvcc -o example example.cu

nvcc命令中的-o选项用于指定输出文件名,而不是输入文件名。 以下是编译名为 example.cu 的 CUDA 源文件并在特定目录中 生成名为 example 的可执行文件

确保 -o 和输出文件路径之间包含空格。 该命令还应包含源代码文件 (example.cu) 和所需输出可执行文件 (/home/user/lcr/example) 的正确路径。

如果是用open mp

user@user-SYS-420GP-TNR:~/lcr/try$ nvcc -o example example.cu
/usr/bin/ld: /tmp/tmpxft_0015851b_00000000-11_example.o: in function `main':
tmpxft_0015851b_00000000-6_example.cudafe1.cpp:(.text+0xfa): undefined reference to `omp_get_num_procs'
/usr/bin/ld: tmpxft_0015851b_00000000-6_example.cudafe1.cpp:(.text+0x24f): undefined reference to `omp_set_num_threads'
/usr/bin/ld: tmpxft_0015851b_00000000-6_example.cudafe1.cpp:(.text+0x254): undefined reference to `omp_get_thread_num'
/usr/bin/ld: tmpxft_0015851b_00000000-6_example.cudafe1.cpp:(.text+0x25f): undefined reference to `omp_get_num_threads'
collect2: error: ld returned 1 exit status

链接过程中找不到 omp_get_num_procs、omp_set_num_threads、omp_get_thread_num、omp_get_num_threads 这些函数的定义。这些函数属于 OpenMP 库,用于并行编程。在代码中可能使用了 OpenMP 的相关函数,但链接时找不到其定义。
解决方法是,需要在链接时显式地添加 OpenMP 库。在使用 nvcc 进行链接时,可以通过 -Xcompiler 选项将链接参数传递给底层编译器(通常是 g++),以链接 OpenMP 库。
尝试使用以下命令编译链接 CUDA C++ 代码,并添加 OpenMP 支持:

nvcc -o example example.cu -Xcompiler -fopenmp

这个命令会将 -fopenmp 选项传递给底层编译器,以链接 OpenMP 库
4. 运行生成的可执行文件

./example

运行结果如下所示
在这里插入图片描述

如果你使用 nvcc -o example example.cu -Xcompiler -fopenmp 成功编译了你的程序,但在运行时没有反应,可能有几个原因导致这种情况。以下是一些可能的解决方法:

  1. 检查代码逻辑和输出:首先,请确保你的 CUDA C++ 代码本身没有逻辑问题。你可以在代码中添加一些输出语句,以便你在运行程序时能够看到一些信息,帮助你确定程序是否在运行。

  2. 命令行运行:尝试在终端中运行你的可执行文件 example,看看是否有任何输出或错误消息。在终端中输入以下命令:
    ./example
    如果程序需要输入参数,确保你提供了正确的参数。

  3. 查看CUDA运行时错误:在运行程序时,CUDA 运行时错误可能会导致程序崩溃或没有输出。你可以在终端中运行以下命令来检查 CUDA 运行时错误:

cuda-memcheck ./example

已经退出.cu所在文件下,为了确保使用正确的可执行文件路径来运行 cuda-memcheck。如果可执行文件名是 example,那么可以使用绝对路径来运行

cuda-memcheck /home/user/lcr/try/example

./home/user/lcr/try/ .是example文件的位置路径
在这里插入图片描述

需要注意的是,cuda-memcheck 工具已经被官方标记为过时,推荐使用 compute-sanitizer 工具作为替代。

compute-sanitizer

是 NVIDIA 提供的一个工具,用于检测 CUDA 应用程序中的内存问题、数据竞争等。下面是如何在 example.cu 文件上使用 compute-sanitizer 工具的基本步骤

  1. 确保已经安装了 CUDA Toolkit 12.0 或更高版本,因为 compute-sanitizer 是在这些版本中引入的。

  2. 打开终端,并切换到包含 example.cu 文件的目录。

  3. 使用以下命令编译 example.cu 文件,并在编译选项中添加 -fsanitize=compute 标志:

nvcc -o example example.cu -Xcompiler -fopenmp -fsanitize=compute

编译完成后,运行生成的可执行文件 ./example
如果在程序中存在 CUDA 相关的问题,compute-sanitizer 会在运行时检测并报告这些问题。
需要注意的是,compute-sanitizer 的使用方式可能会因为不同的 CUDA 版本和工具包而有所不同,具体的细节可以参考 NVIDIA 的官方文档或资源。在使用前,建议查阅相关文档以了解更多详细信息。

在example 可执行文件上使用 compute-sanitizer 工具的步骤:

  1. 确保已经安装了 CUDA Toolkit 12.0 或更高版本,因为 compute-sanitizer 是在这些版本中引入的。

  2. 打开终端,并切换到包含 example 可执行文件的目录。

使用以下命令运行 compute-sanitizer 工具,将你的 example 可执行文件作为参数传递:

compute-sanitizer ./example

compute-sanitizer 将会在运行时检测可执行文件中的 CUDA 相关问题,并输出相应的报告。

一些问题

使用以下命令来查找 CUDA 的安装路径

find / -name libsanitizer-collection.so

将在整个系统中搜索 libsanitizer-collection.so 文件,一旦找到,就可以使用找到的路径来设置环境变量或者直接使用 compute-sanitizer 工具。请确保CUDA 安装已经正确完成,并且路径和文件都存在

找不到 libsanitizer-collection.so 文件。这可能是因为文件不存在或者路径不正确。

以下命令来查看 libsanitizer-collection.so 文件是否存在:

ls /usr/local/cuda/extras/CUPTI/lib64/libsanitizer-collection.so

如果上述库文件存在,尝试将其目录添加到 LD_LIBRARY_PATH 环境变量中。在终端中运行以下命令:

export LD_LIBRARY_PATH=/usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH

然后再次尝试运行 compute-sanitizer

find /usr/local/cuda -name libsanitizer-collection.so

如果文件存在,你可以将路径添加到 LD_LIBRARY_PATH 环境变量中,然后尝试运行 compute-sanitizer。如果文件确实不存在,可能需要检查 CUDA 和 CUPTI 的安装是否完整。

vscode

cuda c++(cuda-gdb),cuda c++(cuda-gdbserver),cuda c++ qnx(cuda-gdbserver),各自是做什么的,有什么作用,如何使用

CUDA C++(cuda-gdb):
CUDA C++ 是 C++ 编程语言的扩展,允许开发人员编写可在传统 CPU 和 NVIDIA GPU 上执行的代码。 CUDA C++ 提供将计算卸载到 GPU 并利用并行性的功能。 cuda-gdb 是 CUDA 程序的 NVIDIA 调试器。 它允许您通过提供断点、观察点、单步执行代码、检查变量和分析内存使用情况等功能在 GPU 上调试 CUDA C++ 程序。

CUDA C++(cuda-gdbserver):
cuda-gdbserver 是用于远程调试场景的实用程序。 它允许您从单独的主机调试目标设备(例如嵌入式系统或具有 GPU 的远程计算机)上的 CUDA 应用程序。 cuda-gdbserver 在目标设备上运行,并与主机上的 cuda-gdb 通信,使您能够远程调试 CUDA 应用程序。

CUDA C++ QNX(cuda-gdbserver):
cuda-gdbserver for QNX 是 cuda-gdbserver 实用程序的一个版本,专门设计用于与 QNX 操作系统配合使用。 QNX 常用于嵌入式系统。 与标准 cuda-gdbserver 类似,该版本允许在 QNX 目标设备上远程调试 CUDA 应用程序。

如何使用:

CUDA C++(cuda-gdb):

安装 cuda-gdb 作为 CUDA 工具包的一部分。
使用 nvcc 编译 CUDA C++ 程序。
使用 cuda-gdb 命令,后跟编译的二进制文件来启动调试器:cuda-gdb my_program。
使用 cuda-gdb 命令设置断点、运行程序、检查变量并分析内存使用情况。

CUDA C++(cuda-gdbserver):

在目标设备上,安装并运行 cuda-gdbserver。
在主机上,使用 nvcc 编译 CUDA C++ 程序。
使用带有 --remote 标志的 cuda-gdb 命令连接到远程 cuda-gdbserver:cuda-gdb --remote=target:port my_program。
调试远程 CUDA 程序,就像它在主机上运行一样。

CUDA C++ QNX(cuda-gdbserver):

请遵循与 cuda-gdbserver 相同的步骤,但请确保您拥有与 QNX 目标设备兼容的 QNX 版本的 cuda-gdbserver。
使用带有 --remote 标志的 cuda-gdb 命令,指定 QNX 目标:cuda-gdb --remote=qnx:port my_program。
请记住,使用 cuda-gdb 和 cuda-gdbserver 等调试工具需要熟悉调试概念和 CUDA 编程。

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

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

相关文章

【必看】时序逻辑仿真成组合逻辑?你知道原因吗?

对于初学者&#xff0c;一般会遇到这种情况&#xff0c;明明写的时序逻辑&#xff0c;结果仿真结果却是组合逻辑&#xff0c;然后看遍设计代码&#xff0c;始终找不到原因&#xff0c;交流群、知乎这种问题随处可见。但不要怀疑软件问题&#xff0c;modelsim这些专用软件基本不…

【100天精通python】Day33:使用python操作数据库_SQLite数据库的使用与实战

目录 专栏导读 1 SQLite 简介 2 SQLite数据库安装及使用 2.1 检查 SQLite 支持 2.2 创建数据库文件 2.2.1 使用 Python 创建数据库文件&#xff1a; 2.2.2 使用命令行创建数据库文件&#xff1a; 2.3 连接到 SQLite 数据库&#xff1a; 3 SQLite 中常用的SQL语句…

WebRTC音视频通话-实现iOS端调用ossrs视频通话服务

WebRTC音视频通话-实现iOS端调用ossrs视频通话服务 之前搭建ossrs服务&#xff0c;可以查看&#xff1a;https://blog.csdn.net/gloryFlow/article/details/132257196 这里iOS端使用GoogleWebRTC联调ossrs实现视频通话功能。 一、iOS端调用ossrs视频通话效果图 iOS端端效果图…

HTML详解连载(7)

HTML详解连载&#xff08;7&#xff09; 专栏链接 [link](http://t.csdn.cn/xF0H3)下面进行专栏介绍 开始喽结构伪类选择器作用 :nth-child&#xff08;公式&#xff09;作用举例 伪元素选择器作用注意&#xff1a; PxCoook作用盒子模型-重要组成部分 盒子模型-边框线属性名属性…

Java-运算符和控制语句(上)(基于c语言的补充)

算术运算符 关于求余 不管分子&#xff0c;分母是正还是负&#xff0c;对于分母&#xff0c;直接取正&#xff1b;对于分子若有负号&#xff0c;则先提取出来&#xff1b;剩下两个正的分子分母运算&#xff1b;最后&#xff0c;若刚才的分子有负号&#xff0c;对最后的结果添加…

fork:创建一个子进程

函数原型&#xff1a;pid_t fork&#xff08;void&#xff09;&#xff1b; 返回值&#xff1a; 成功&#xff1a;返回子进程id给附近父进程&#xff0c;返回0给子进程 失败&#xff1a;返回-1&#xff0c;并且设置错误号&#xff0c;同时子进程不会被创建 注意&#xff1…

C++ QT(一)

目录 初识QtQt 是什么Qt 能做什么Qt/C与QML 如何选择Qt 版本Windows 下安装QtLinux 下安装Qt安装Qt配置Qt Creator 输入中文配置Ubuntu 中文环境配置中文输入法 Qt Creator 简单使用Qt Creator 界面组成Qt Creator 设置 第一个Qt 程序新建一个项目项目文件介绍项目文件*.pro样式…

锁与原子操作的底层原理

偏向锁 在一个系统当中&#xff0c;大部分时间都不存在并发问题&#xff0c;但频繁的加锁释放锁又会占用大量系统资源。因此为了让线程获得锁的代价更低而引入了偏向锁。 获得偏向锁 1&#xff09;检查该锁是否被当前线程持有 2&#xff09;通过CAS操作修改对象头 3&#…

python环境下载安装教程,python运行环境怎么下载

本篇文章给大家谈谈python安装步骤以及环境变量配置&#xff0c;以及下载python需要设置环境变量吗&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 1.https://www.python.org/downloads/windows/ 下载适合自己电脑的python安装包 2.下载后安装即可 3.配置环…

Vue中如何更好地封装组件?

子组件接受父组件传递的事件 1.子组件使用事件名"$emit(父组件中传递的事件名,想给父组件传递的参数(可选))" click"$emit(click)" 2.子组件使用 v-on"$listeners" 父组件&#xff1a; <template><div id"app"><myCo…

Ceph分布式存储系统优化分析

Ceph支持多种存储访问接口&#xff0c;现有的多种性能测试工具都可用于Ceph的性能测试&#xff0c;如测试块接口性能的fio&#xff0c;iometer等&#xff1b;测试CephFS接口的filebench&#xff0c;fio等;测试对象接口的cosbench等。Ceph有专用的基准测试集CBT&#xff0c;其包…

并查集的原理与实现

1.概念 2.生活中的例子 小弟-老大&#xff1b; 帮派识别 3.实现 3.1 初始化 3.2 中间过程 3.3合并 3.4 并查集路径优化 直接把下面的节点指向最终的老大。 3.5 伪代码实现 3.6JAVA实现 findRoot: 谁是帮派的老大。例如山鸡的老大是陈浩南 connected: 我们是不是同一个大…

【机器学习 | 数据预处理】 提升模型性能,优化特征表达:数据标准化和归一化的数值处理技巧探析

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

勇敢牛牛,爱吃青草

牛顿问题&#xff08;牛吃草问题 / 消长问题&#xff09; 牛顿问题&#xff08;牛吃草问题/消长问题&#xff09; 牛顿问题&#xff08;牛吃草问题/消长问题&#xff09; 牧场上有一片青草&#xff0c;每天都生长得一样快。这片青草供给 10 头牛吃&#xff0c;可以吃 22 天&…

元宇宙时代超高清视音频技术白皮书关于流媒体协议和媒体传输解读

流媒体协议 元宇宙业务场景对流媒体传输的实时性和互动性提出了更高的要求&#xff0c;这就需要在传统的 RTMP、SRT、 HLS 等基础上增加实时互动的支持。实时互动&#xff0c;指在远程条件下沟通、协作&#xff0c;可随时随地接入、实时地传递虚实融合的多维信息&#xff0c;身…

LangChain-ChatGLM在WIndows10下的部署

LangChain-ChatGLM在WIndows10下的部署 参考资料 1、LangChain ChatGLM2-6B 搭建个人专属知识库中的LangChain ChatGLM2-6B 构建知识库这一节&#xff1a;基本的逻辑和步骤是对的&#xff0c;但要根据Windows和现状做很多调整。 2、没有动过model_config.py中的“LORA_MOD…

Idea中使用statement接口对象,显示mysql版本号,所有库和表名

使用statement 接口对象&#xff0c;进行以下操作&#xff1a; 显示数据库版本号显示所有库显示所有库中的table表 显示数据库版本号&#xff1a; public class StatementDemo {Testvoid showall(){try{Statement st conn.createStatement();ResultSet rs st.executeQuery(…

C++_模板初阶

在面向对象中&#xff0c;我们可以使用重载来实现多态。 但是问题在于&#xff0c;重载的函数仅仅是类型不同&#xff0c;代码复用率比较低&#xff0c;只要有新的类型出现时&#xff0c;就要增加对应的函数&#xff1b;另一方面它的代码可维护性比较低&#xff0c;一个出错可…

python递归实现逆序输出数字

一、问题描述 编程实现将输入的整数逆序输出 二、问题分析 逆序输出数字实际是一个数值问题的递归 三、算法设计 该问题要求输入任意一个整数&#xff0c;实现它的逆序输出。首先判断输入的整数是正整数还是负整数&#xff0c;如果是负整数&#xff0c; 则在逆序输出前应先…

1059 Prime Factors

个人学习记录&#xff0c;代码难免不尽人意。 Sample Input: 97532468 Sample Output: 975324682^211171011291 下面是我第一次自己写的错误代码&#xff0c;虽然测试点都通过了&#xff0c;但是是因为测试样例有限的原因。 #include<cstdio> #include<iostream> #…