QT+CUDA 同时编译Qt和CUDA代码

news2024/11/22 22:18:50

        工作需要把cuda的代码移植到QT中,和Qt项目一起编译,这里记录一下。


前期准备

1.安装CUDA

        电脑需要安装好 CUDA,可以看我的这篇文章安装:Windows和WSL安装CUDA-CSDN博客

        使用命令 nvcc --version 查看安装的 CUDA 版本。

        CUDA 的默认的安装路径是: 

# CUDA_PATH  这个是安装cuda时自动配置到环境变量中的路径,也是cuda安装的路径
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6

2.安装CUDA Samples

        电脑需要安装CUDA Samples,CUDA Samples 是 CUDA 官方提供的示例程序,默认的安装路径是

C:\Program Files\NVIDIA Corporation\CUDA Samples\v12.6
# CUDA_SDK   sdk包的位置
C:\Program Files\NVIDIA Corporation\CUDA Samples\v12.6\common

        官方文档中说 CUDA Samples 在 CUDA 11.6 版本之后就不会随着 CUDA 一起默认安装了,所以如果你安装的是高于CUDA 11.6 版本的话,需要去 GitHub 上GitHub - NVIDIA/cuda-samples at v12.5 自己下载 CUDA Samples。

3. 新建文件夹

        由于在配置Qt时,pro文件中的 CUDA 路径不能有空格,而 CUDA 和 CUDA Samples 的默认安装路径都有空格。所以新建一个文件夹,把上面两步 CUDA_PATH  和 CUDA_SDK 路径下的内容全部拷贝过去。

# 我新建的文件夹
E:\MyWorkSpace\Qt\cuda


Qt配置

        首先新建一个带界面的Qt程序,

        修改pro文件,里面的路径和部分配置需要改成匹配你自己电脑的:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = TestCuda
CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    MainWindow.cpp

HEADERS += \
    MainWindow.h \
    kernel.h 

FORMS += \
    MainWindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

#-------------------------------------------------
# CUDA
# This makes the .cu files appear in your project
CUDA_SOURCES += \
    kernel.cu

# CUDA settings
SYSTEM_NAME = x64                   # Depending on your system either 'Win32', 'x64', or 'Win64'
SYSTEM_TYPE = 64                    # '32' or '64', depending on your system
#不同的显卡注意填适当的选项,使用命令 nvidia-smi --query-gpu=compute_cap --format=csv 查询
CUDA_ARCH = sm_86                   # Type of CUDA architecture
NVCC_OPTIONS = --use_fast_math
#-------------------------------------------------
win32 {
    # Define output directories
    DESTDIR = ./bin
    CUDA_OBJECTS_DIR = ./
    #注意文件路径不能有空格!
    CUDA_DIR = "E:/MyWorkSpace/Qt/cuda"         # Path to cuda toolkit install
    LIBS += -L$$CUDA_DIR/lib/x64 \
        -lcudart \
        -lcublas \
        -lcufft

    # MSVCRT link option (static or dynamic, it must be the same with your Qt SDK link option)
    MSVCRT_LINK_FLAG_DEBUG   = "/MDd"           #表示使用DLL的调试版
    MSVCRT_LINK_FLAG_RELEASE = "/MD"            #使用DLL版的C和C++运行库 具体可以看vs的属性设置

    # include paths
    INCLUDEPATH += $$CUDA_DIR\include \
        $$CUDA_DIR/Common

    # library directories
    QMAKE_LIBDIR += $$CUDA_DIR\lib\$$SYSTEM_NAME

    # The following makes sure all path names (which often include spaces) are put between quotation marks
    CUDA_INC = $$join(INCLUDEPATH,'" -I"','-I"','"')

    # Add the necessary libraries
    CUDA_LIB_NAMES = cudart_static

    for(lib, CUDA_LIB_NAMES) {
        CUDA_LIBS += -l$$lib
    }
    LIBS += $$CUDA_LIBS

    # Configuration of the Cuda compiler
    CONFIG(debug, debug|release) {
        # Debug mode
        cuda_d.input = CUDA_SOURCES
        cuda_d.output = $$CUDA_OBJECTS_DIR\${QMAKE_FILE_BASE}_cuda.obj
        cuda_d.commands = "$$CUDA_DIR\bin\nvcc.exe" -D_DEBUG $$NVCC_OPTIONS $$CUDA_INC $$CUDA_LIBS \
                          --machine $$SYSTEM_TYPE -arch=$$CUDA_ARCH \
                          --compile -cudart static -g -DWIN32 -D_MBCS \
                          -Xcompiler "/wd4819,/EHsc,/W3,/nologo,/Od,/Zi,/RTC1" \
                          -Xcompiler $$MSVCRT_LINK_FLAG_DEBUG \
                          -c -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
        cuda_d.dependency_type = TYPE_C
        QMAKE_EXTRA_COMPILERS += cuda_d
    }
    else {
        # Release mode
        cuda.input = CUDA_SOURCES
        cuda.output = $$CUDA_OBJECTS_DIR\${QMAKE_FILE_BASE}_cuda.obj
        cuda.commands = $$CUDA_DIR\bin\nvcc.exe $$NVCC_OPTIONS $$CUDA_INC $$CUDA_LIBS \
                        --machine $$SYSTEM_TYPE -arch=$$CUDA_ARCH \
                        --compile -cudart static -DWIN32 -D_MBCS \
                        -Xcompiler "/wd4819,/EHsc,/W3,/nologo,/O2,/Zi" \
                        -Xcompiler $$MSVCRT_LINK_FLAG_RELEASE \
                        -c -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
        cuda.dependency_type = TYPE_C
        QMAKE_EXTRA_COMPILERS += cuda
    }
}

#-------------------------------------------------
unix {
    # Define output directories
    DESTDIR = ./bin
    CUDA_OBJECTS_DIR = ./
    CUDA_DIR = "/usr/local/cuda-10.0"            # Path to cuda toolkit install
    LIBS += -L"/usr/local/lib" \
            -L"/usr/local/cuda/lib64" \
            -lcudart

    # include paths
    INCLUDEPATH += $$CUDA_DIR/include \
                   $$CUDA_DIR/common/inc \
                   $$CUDA_DIR/../shared/inc

    # library directories
    QMAKE_LIBDIR += $$CUDA_DIR\lib64

    # The following makes sure all path names (which often include spaces) are put between quotation marks
    CUDA_INC = $$join(INCLUDEPATH,'" -I"','-I"','"')

    # Add the necessary libraries
    CUDA_LIB_NAMES = cudart_static

    for(lib, CUDA_LIB_NAMES) {
        CUDA_LIBS += -l$$lib
    }
    LIBS += $$CUDA_LIBS

    # Configuration of the Cuda compiler
    CONFIG(debug, debug|release) {
        # Debug mode
        cuda_d.input = CUDA_SOURCES
        cuda_d.output = $$CUDA_OBJECTS_DIR\${QMAKE_FILE_BASE}_cuda.o
        cuda_d.commands = $$CUDA_DIR/bin/nvcc -D_DEBUG $$NVCC_OPTIONS $$CUDA_INC $$CUDA_LIBS \
                          --machine $$SYSTEM_TYPE -arch=$$CUDA_ARCH \
                          --compile -cudart static -g -DWIN32 -D_MBCS \
                          -c -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
        cuda_d.dependency_type = TYPE_C
        QMAKE_EXTRA_COMPILERS += cuda_d
    }
    else {
        # Release mode
        cuda.input = CUDA_SOURCES
        cuda.output = $$CUDA_OBJECTS_DIR\${QMAKE_FILE_BASE}_cuda.obj
        cuda.commands = $$CUDA_DIR/bin/nvcc $$NVCC_OPTIONS $$CUDA_INC $$CUDA_LIBS \
                        --machine $$SYSTEM_TYPE -arch=$$CUDA_ARCH \
                        --compile -cudart static -DWIN32 -D_MBCS \
                        -c -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
        cuda.dependency_type = TYPE_C
        QMAKE_EXTRA_COMPILERS += cuda
    }
}

        CUDA 文件的头文件,kernel.h

#ifndef KERNEL_H
#define KERNEL_H

#define  WIDTH 11

#define  HEIGHT 10
#define  X_INTER 3
#define  Y_INTER 3
#define  BLOCK_SIZE 8

// Adds two arrays
void runCudaPart();

#endif // KERNEL_H

        CUDA 文件,kernel.cu,可以通过添加新文件中—>通用—>空文件创建:

#include "kernel.h"

// CUDA-C includes
#include <cuda.h>
#include <cuda_runtime.h>

#include <stdio.h>
#include <iostream>
#include <chrono>

const int Width = 4;

// CUDA内核函数:计算矩阵乘积
__global__ void MatrixMulKernel(float* Md, float* Nd, float* Pd) {
    unsigned long long start_time = clock();
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    float sum = 0.0f;
    for (int k = 0; k < Width; ++k) {
        sum += Md[row * Width + k] * Nd[k * Width + col];
    }

    Pd[row * Width + col] = sum;

    // 获取结束时间戳
    unsigned long long end_time = clock();

    // 打印时间差(精确到微秒)
    if (threadIdx.x == 0 && threadIdx.y == 0) {
        printf("Thread [%d, %d] Execution Time: %llu microseconds\n", blockIdx.x, blockIdx.y, end_time - start_time);
    }
}

void runCudaPart()
{
    float array1[Width][Width] = {
            {1.0f, 2.0f, 3.0f, 4.0f},
            {5.0f, 6.0f, 7.0f, 8.0f},
            {9.0f, 10.0f, 1.0f, 2.0f},
            {3.0f, 4.0f, 5.0f, 6.0f}
        };

    float array2[Width][Width] = {
        {7.0f, 8.0f, 9.0f, 10.0f},
        {1.0f, 2.0f, 3.0f, 4.0f},
        {5.0f, 6.0f, 7.0f, 8.0f},
        {9.0f, 10.0f, 1.0f, 2.0f}
    };

    float* Md;
    float* Nd;
    float* Pd;

    // 分配内存并复制数据到设备
    cudaMalloc(&Md, Width * Width * sizeof(float));
    cudaMalloc(&Nd, Width * Width * sizeof(float));
    cudaMalloc(&Pd, Width * Width * sizeof(float));

    cudaMemcpy(Md, array1, Width * Width * sizeof(float), cudaMemcpyHostToDevice);
    cudaMemcpy(Nd, array2, Width * Width * sizeof(float), cudaMemcpyHostToDevice);

    const int tileSize = 2;

    // 定义网格和线程块大小
    dim3 threadsPerBlock(Width / tileSize, Width / tileSize);
    dim3 numBlocks(tileSize, tileSize);

    // 获取开始时间
    auto start_time = std::chrono::high_resolution_clock::now();

    // 启动内核
    MatrixMulKernel<<<numBlocks, threadsPerBlock>>>(Md, Nd, Pd);

    // 获取结束时间
    auto end_time = std::chrono::high_resolution_clock::now();
    // 计算执行时间
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
    std::cout << "Execution Time: " << duration << " microseconds" << std::endl;

    // 将结果从设备复制回主机
    float result[Width][Width];
    cudaMemcpy(result, Pd, Width * Width * sizeof(float), cudaMemcpyDeviceToHost);

    // 打印结果
    for (int i = 0; i < Width; ++i) {
        for (int j = 0; j < Width; ++j) {
            std::cout << result[i][j] << " ";
        }
        std::cout << std::endl;
    }

    // 释放内存
    cudaFree(Md);
    cudaFree(Nd);
    cudaFree(Pd);
}

        MainWindow的UI文件中加一个按钮,MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

 MainWindow.cpp

#include "MainWindow.h"
#include "ui_MainWindow.h"

#include "kernel.h"

#include <iostream>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    std::cout << "11111111" << std::endl;
    runCudaPart();
    std::cout << "22222222" << std::endl;
}

        运行程序可以看到打印,大功告成!

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

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

相关文章

通过API构建开放式外卖系统平台:合作伙伴的集成与管理

随着外卖行业的迅速发展&#xff0c;外卖系统平台的开放性和可扩展性变得尤为重要。通过API构建一个开放式的外卖系统平台&#xff0c;企业可以更轻松地与合作伙伴进行集成和管理。本文将探讨如何通过API构建开放式外卖系统平台&#xff0c;并通过代码示例展示与合作伙伴的集成…

md-editor-v3适配VUE3的MarkDown编辑器-好用-简单-免费

官方文档&#xff1a; https://imzbf.github.io/md-editor-v3/zh-CN/indexhttps://imzbf.github.io/md-editor-v3/zh-CN/index 效果演示&#xff1a;&#xff08;支持黑暗模式切换&#xff09; toolbar包括&#xff1a; [bold,underline,italic,strikeThrough,title,sub,sup…

系统编程 day13 进程5

前提&#xff1a; 信息量&#xff1a;线程间有序的进行工作 资源的个数 机制&#xff1a;描述可使用资源的个数 操作&#xff1a; p操作&#xff1a;使用这个资源&#xff0c;表示资源个数减1 v操作&#xff1a;产生这个资源&#xff0c;表示资源个数加1 p操作逻辑&…

CoCoOp(论文解读):Conditional Prompt Learning for Vision-Language Models

摘要 随着预训练的视觉语言模型&#xff08;如 CLIP&#xff09;的兴起&#xff0c;研究使这些模型适应下游数据集的方法变得至关重要。最近CoOp方法将NLP领域中的提示学习引入到视觉领域中&#xff0c;来调整预训练的视觉语言模型。具体来说&#xff0c;CoOp 将提示中的上下文…

DataGridView用法合集(9):添加控件

目录 45. DataGridView列中显示选择框CheckBox 46. DataGridView中显示下拉框ComboBox 47. DataGridView单击打开下拉框 48. DataGridView中显示按钮 49. DataGridView中显示链接 50. DataGridView中显示图像 45. DataGridView列中显示选择框CheckBox [VB.NET] 添加Chec…

MySQL5.7数据库---入门教程(小白教程)

一、MySQL安装 本文以MySQL5.7安装为例。在设置完root密码和添加一个用户后&#xff0c;一路默认。 1、 2、通过点击红圈里的箭头选择对应的版本。 3、 4、端口&#xff08;Port&#xff09;一般默认不需要更改。 5、 二、配置环境变量 配置环境变量可以方便在win系统中cmd…

HarmonyOS 端云一体化 -- 项目初始化

HarmonyOS 端云一体化 – 项目初始化 端云一体化官方简介 本文档基于 api9 编写本来我想用最新版的api搞&#xff0c;但是在 AppFallery Connect 上创建项目的时候有bug&#xff0c;没没办法成功创建应用&#xff0c;无奈只能切换到 api9 版本。 1.新建项目 1.1 登录华为官…

突破大模型极限!GLM-4-long百万长文本模型上线bigmodel.cn

最近业务上多了长文本的需求&#xff0c;因为要在prompt里面塞进比较多的rag内容&#xff0c;以供决策&#xff0c;且这些召回的内容&#xff0c;都有可能用到。这非常考验大模型的长文本能力&#xff0c;技术选型上都要着重考察这部分。 正巧&#xff0c;上次清影试用后&…

游戏开放式新手引导框架设计

强制性引导&#xff1a;只能点某个按钮 优&#xff1a;程序简单 缺&#xff1a; 玩家体验差 开放式引导&#xff1a;不强制点 优&#xff1a;玩家体验好 缺&#xff1a; 程序复杂 需求分析&#xff1a; 1.开放式引导&#xff0c;引导是到达某个条件后进行一系列行为&#xff08…

水星Mercury X1轮式人形机器人结合openc算法&STag标记码视觉系统实现精确抓取!

本案例展示了如何利用视觉系统提升机械臂的抓取精度&#xff0c;成功实现了人形机器人的双臂抓取不在局限于单臂抓取。 引言 如今市面上已经有了许多不同类型的人形机器人&#xff0c;涵盖了服务行业和医疗行业等各个领域。这些机器人以其智能化和自动化的特性逐渐融入我们的日…

比例PQ阀信号放大器的选择

比例PQ阀信号放大器的选择时&#xff0c;需要考虑一系列的因素以确保放大器能精确匹配比例阀的需求&#xff0c;保障液压系统的高效和稳定运行。根据所控制的比例阀类型&#xff0c;选择与之兼容的放大器型号。如各厂商不带反馈比例方向阀、比例溢流阀、比例减压阀等均可用BEUE…

RabbitMQ 集群部署方案

RabbitMQ 一、安装 RabbitMQ二、更改配置文件三、配置集群四、测试 环境准备&#xff1a;三台服务器&#xff0c;系统是 CentOS7IP地址分别是&#xff1a; rabbitmq1&#xff1a;192.168.152.71rabbitmq2&#xff1a;192.168.152.72rabbitmq3&#xff1a;192.168.152.73 一、…

【一键操作】【包运行及安装教程】2024数学建模国赛(高教社杯)Latex论文模板

数学建模国赛创办于1992年&#xff0c;每年一届&#xff0c;是首批列入“高校学科竞赛排行榜”的19项竞赛之一。 作为一个重量级的赛事&#xff0c;一次参赛将众生受益&#xff0c;所以相信很多同学都在为了国奖而努力&#xff0c;所以针对大家的参赛论文&#xff0c;我们之前分…

LVS集群的NAT模式和DR模式

LVS简介 LVS&#xff08;Linux Virtual Server&#xff09;是一个用于负载均衡的开源软件项目&#xff0c;旨在通过集群技术实现高性能、高可用的服务器系统。它运行在Linux操作系统上&#xff0c;并且可以利用内核级的资源来提高性能和稳定性。 LVS 体系结构 LVS架构 主要…

Redis远程字典服务器(7)—— set类型详解

目录 一&#xff0c;基本情况 二&#xff0c;常用命令 2.1 sadd 2.2 smembers&#xff0c;sismember 2.3 spop&#xff0c;srandmember 2.3 smove&#xff0c;srem 2.4 sinter&#xff0c;sinterstore求交集 2.5 sunion&#xff0c;sunionstore求并集 2.6 sdiff&#…

Mysql视图整理

理论 初级语法及操作 操作基于navicat视图化&#xff0c;其他管理工具基本类似 参考即可 这里附上官网免费版下载链接&#xff1a;Navicat Premium Lite | 简单的数据库管理和开发工具 首先&#xff1a;选择选中数据库--》最上面的视图--》新建视图--》 我们可以看到这里&a…

three.js 几何体、材质和网格模型

场景Scene、相机Camera、渲染器Renderer初始化完成之后&#xff0c;可以向场景中添加一个简单的模型进行展示。在此之前需要了解三个概念&#xff1a;几何体、材质、网格模型。 几何体&#xff1a;表示物体的几何形状。材质&#xff1a;表示物体的外观效果。网格模型&#xff…

springboot的学习(一):springboot的基础

简介 springboot的基础的知识点的学习总结 springboot 设计目的是为了简化spring应用的初始搭建和开发过程。 简单例子 new project&#xff0c;一般用这个阿里的地址&#xff1a;https://start.aliyun.com/ 点击next&#xff0c;选择jdk版本 点击next&#xff0c;选择模…

88.SAPUI5 Model Binding的问题-在view更改数据,model却不变

目录 1.背景 2.sap.ui.model.BindingMode sap.ui.model.BindingMode.OneWay sap.ui.model.BindingMode.TwoWay 3.oModel.setDefaultBindingMode 方法说明 execOneWay方法 execTwoWay方法 1.背景 在做一个UI5项目&#xff0c;后台读取sap.ui.model.Model后&#xff0c;把…

Vuex 深度解析 | 面试常问问题案例

Vuex 深度解析 | 面试常问问题案例 Vuex 是 Vue.js 应用程序的状态管理模式和库。它为 Vue.js 应用程序提供了一个集中存储所有组件的共享状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。接下来&#xff0c;我们将深入探讨 Vuex 的核心概念、使用方式、AP…