C++開發基礎之初探CUDA計算環境搭建

一、前言

項目中有使用到CUDA計算的相關內容。但是在早期CUDA計算環境搭建的過程中,并不是非常順利,編寫此篇文章記錄下。對于剛剛開始研究的你可能會有一定的幫助。

二、環境搭建

搭建 CUDA 計算環境涉及到幾個關鍵步驟,包括安裝適當的 CUDA 驅動程序和工具包、設置開發環境和編譯器,以及編寫和運行 CUDA 程序。感謝Davis lee詳細的介紹 CUDA安裝及環境配置——最新詳細版以下是一個基本的搭建過程:

步驟 1:檢查硬件兼容性

首先,確保的計算機上的 GPU 支持 CUDA。可以在 NVIDIA 的官方網站上查找 GPU 的型號以確定其是否支持 CUDA。
在這里插入圖片描述

步驟 2:安裝 CUDA 驅動程序

訪問 NVIDIA 的官方網站,下載并安裝與你的 GPU 兼容的最新 CUDA 驅動程序。安裝過程中,根據向導提示進行操作。
在這里插入圖片描述

步驟 3:安裝 CUDA 工具包

下載并安裝與你的 CUDA 驅動程序版本相匹配的 CUDA 工具包。CUDA 工具包中包含了編譯器、庫和工具,用于開發和運行 CUDA 程序。

https://developer.nvidia.com/cuda-downloads

步驟 4:安裝適當的開發環境

你可以使用多種開發環境來編寫 CUDA 程序,如 NVIDIA 提供的 CUDA Toolkit 中自帶的 nvcc 編譯器,或者集成了 CUDA 開發支持的 IDE,如 Visual Studio(需要安裝適當的 CUDA 插件)或 JetBrains 的 CLion 等。

步驟 5:設置環境變量

在你的操作系統中設置 CUDA 相關的環境變量,包括 PATHCUDA_PATH 等,以便系統可以找到 CUDA 工具和庫。

步驟 6:編寫和編譯 CUDA 程序

使用你選擇的開發環境編寫 CUDA 程序,并使用 CUDA 編譯器(如 nvcc)編譯程序。確保您的程序正確地鏈接了 CUDA 庫,并且編譯選項正確設置。

步驟 7:運行 CUDA 程序

將編譯生成的可執行文件部署到你的計算機上,并在 CUDA 支持的環境中運行程序。你可能需要在程序運行時指定相應的 GPU 設備。

總之就是,在搭建時適配自己的電腦配置要求。做到最新即可。

三、實踐編碼過程

新增一個空的解決方案,我們命名為VectorProject.sln。

3.1 使用CUDA編寫動態庫

1、新增動態鏈接庫 ,命名為VectorLibrary;

2、配置CUDA編譯環境:
生成依賴項–>生成自定義
在這里插入圖片描述
選擇CUDA 12.3(targets,props)
在這里插入圖片描述
這里如果不配置CUDA編譯環境,會報錯,無法正常編譯通過的。配置完成后,可以查看項目的屬性頁。能看到CUDA C/C++配置部分
在這里插入圖片描述
3、編寫接口代碼

這里主要定義兩個向量的加法運算。

#pragma once
#include "pch.h"
#include <Windows.h>#ifdef VECTOR_LIBRARY_EXPORTS
#define VECTOR_LIBRARY_API __declspec(dllexport)
#else
#define VECTOR_LIBRARY_API __declspec(dllimport)
#endifBOOL VECTOR_LIBRARY_API vectorAddCPU(const float* A, const float* B, float* C, int N);
BOOL VECTOR_LIBRARY_API vectorAddGPU(const float* A, const float* B, float* C, int N);

4、編寫CPU方法實現過程

// 封裝CUDA函數的C++代碼
#include "pch.h"
#include "vectorAdd.h"// CPU上的向量加法函數BOOL vectorAddCPU(const float* A, const float* B, float* C, int N)
{for (int i = 0; i < N; ++i) {C[i] = A[i] + B[i];}return true;
}

5、編寫GPU方法實現過程
新增一個核函數聲明文件 kernelVectorAdd.cuh

#include <iostream>
void kernelVectorAdd(const float* A, const float* B, float* C, int N);

編寫核函數實現

#include <cuda_runtime.h>
#include <iostream>
#include <vector>
#include <device_launch_parameters.h>
#include "kernelVectorAdd.cuh"// CUDA核函數:在GPU上執行的向量加法
__global__ void kernelVectorAddImp(const float* A, const float* B, float* C, int N) {int i = blockDim.x * blockIdx.x + threadIdx.x;if (i < N) {C[i] = A[i] + B[i];}
}void kernelVectorAdd(const float* A, const float* B, float* C, int N) {float* d_A, * d_B, * d_C;size_t size = N * sizeof(float);// 分配設備內存cudaMalloc(&d_A, size);cudaMalloc(&d_B, size);cudaMalloc(&d_C, size);// 將數據從主機內存復制到設備內存cudaMemcpy(d_A, A, size, cudaMemcpyHostToDevice);cudaMemcpy(d_B, B, size, cudaMemcpyHostToDevice);// 執行CUDA核函數int threadsPerBlock = 256;int blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock;kernelVectorAddImp <<<blocksPerGrid, threadsPerBlock >>> (d_A, d_B, d_C, N);// 等待所有CUDA核函數執行完畢cudaDeviceSynchronize();// 將結果從設備內存復制回主機內存cudaMemcpy(C, d_C, size, cudaMemcpyDeviceToHost);// 釋放設備內存cudaFree(d_A);cudaFree(d_B);cudaFree(d_C);
}

在編寫核函數調用的C++代碼

// 封裝CUDA函數的C++代碼
#include "pch.h"
#include "kernelVectorAdd.cuh"
#include "vectorAdd.h"BOOL vectorAddGPU(const float* A, const float* B, float* C, int N) {kernelVectorAdd(A, B, C, N);return true;
}

這里需要把核函數進行封裝,否則會報錯,相關解決辦法可見 關于CUDA C 項目中“ error C2059: 語法錯誤:“<” ”問題的解決方法.

6、現在我們編譯下項目
在這里插入圖片描述

3.2 編寫C++控制臺程序

1、新增C++控制臺程序,VectorCpp
在這里插入圖片描述
2、配置VectorLibrary.dll的引用
打開屬性頁,找到C/C++目錄,附加包含目錄添加配置

$(SolutionDir)VectorLibrary;

在這里插入圖片描述
鏈接器–>常規–>附加庫目錄

$(TargetDir);%(AdditionalLibraryDirectories)

在這里插入圖片描述
鏈接器–>輸入–>附加依賴項

VectorLibrary.lib;%(AdditionalDependencies)

在這里插入圖片描述
配置完成這些,就可以對VectorLibrary.dll正常引用了。

2、編寫調用代碼

// CudaWrapper.cpp
#include "pch.h"
#include <iostream>
#include <random>
#include <chrono>
#include "vectorAdd.h"// 生成隨機數并填充到數組
void generateRandomNumbers(float* array, int N) {unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();std::default_random_engine generator(seed);std::uniform_real_distribution<float> distribution(0.0, 1.0); // 范圍從0到1之間for (int i = 0; i < N; ++i) {array[i] = distribution(generator);}
}int main()
{int N = 1000000;float* pA = new float[N];float* pB = new float[N];float* pC_GPU = new float[N];float* pC_CPU = new float[N];// 為pA和pB生成隨機數generateRandomNumbers(pA, N);generateRandomNumbers(pB, N);// 測量 CPU 端向量加法函數的執行時間auto start_cpu = std::chrono::high_resolution_clock::now();vectorAddCPU(pA, pB, pC_CPU, N);auto end_cpu = std::chrono::high_resolution_clock::now();std::chrono::duration<double> elapsed_cpu = end_cpu - start_cpu;std::cout << "CPU 端向量加法函數的執行時間: " << elapsed_cpu.count() << " 秒" << std::endl;// 測量 GPU 端向量加法函數的執行時間auto start_gpu = std::chrono::high_resolution_clock::now();vectorAddGPU(pA, pB, pC_GPU, N);auto end_gpu = std::chrono::high_resolution_clock::now();std::chrono::duration<double> elapsed_gpu = end_gpu - start_gpu;std::cout << "GPU 端向量加法函數的執行時間: " << elapsed_gpu.count() << " 秒" << std::endl;// 驗證結果for (int i = 0; i < N; ++i){if ((pC_CPU[i] - pC_GPU[i]) > 1e-5){std::cout << "結果不匹配" << std::endl;break;}}std::cout << "結果匹配" << std::endl;// 記得釋放內存delete[] pA;delete[] pB;delete[] pC_CPU;delete[] pC_GPU;return 0;
}

3、運行程序
完整的項目結構
在這里插入圖片描述
運行結果
在這里插入圖片描述
在這個示例中,成功運行得出結果。這個時候,你會發現為什么CPU的計算結果遠遠高于GPU。那是因為:

  • 數據傳輸開銷:在CUDA中,數據必須在主機(CPU)和設備(GPU)之間進行傳輸。在每次調用CUDA函數之前和之后,都需要將數據從主機內存復制到設備內存,然后將結果從設備內存復制回主機內存。這些數據傳輸的開銷會降低CUDA的性能,特別是當數據量較大時。
  • Kernel調用開銷:在CUDA中,每次調用核函數都需要一定的開銷,包括啟動核函數、將數據傳遞給核函數、核函數在GPU上執行等。如果向量大小較小,核函數的啟動開銷可能會占據相當大的比例,從而降低CUDA的性能。
  • 并行化效率不佳:在某些情況下,CUDA核函數可能無法充分利用GPU的并行計算能力。這可能是因為向量大小太小,無法充分填充GPU的計算單元,或者核函數的計算密度不夠高,無法實現最大的并行化效率。
  • 內存訪問模式:CUDA核函數的性能受到內存訪問模式的影響。如果核函數中的內存訪問模式不利于GPU的緩存和內存訪問優化,性能可能會受到影響。

究其根本原因就是,這個算法太簡單了,CPU就可以搞定,用不上GPU。

四、總結

在這個項目中,我們主要體會框架的用法,以及CUDA計算環境搭建的。通過編碼實踐,構建項目成功實驗了CUDA計算環境搭建,為接下來的工作準備好環境。

五、參考文檔

錯誤 MSB4062 未能從程序集加載任務

VS加載CUDA項目出錯:未找到導入的項目

整理:warning LNK4098: 默認庫“LIBCMT”與其他庫的使用沖突;請使用 /NODEFAULTLIB:library

Win10下在VS2019中配置使用CUDA進行加速的C++項目 (配置.h文件,.dll以及.lib文件等)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/23684.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/23684.shtml
英文地址,請注明出處:http://en.pswp.cn/web/23684.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【SCSS】use的詳細使用規則

目錄 use加載成員選擇命名空間私有成員配置使用 Mixin重新賦值變量 use 從其他 Sass 樣式表中加載 mixins、函數和變量&#xff0c;并將來自多個樣式表的 CSS 組合在一起。use加載的樣式表被稱為“模塊”。 加載成員 // src/_corners.scss $radius: 3px;mixin rounded {bord…

Hive面試問題

1.hive如何自定義函數 2.hive優化 3.hive數據傾斜 1.數據傾斜的表現 數據傾斜是由于數據分布不均勻&#xff0c;造成數據大量的集中到一點&#xff0c;造成數據熱點的現象。 主要表現&#xff1a;任務進度長時間維持在 99%或者 100%的附近&#xff0c;查看任務監控頁面Yarn(808…

分析示例 | Simufact焊接工藝仿真變形精確預測汽車結構

導語 焊接是汽車制造過程中一個關鍵環節&#xff0c;白車身、發動機、底盤和變速箱等都離不開焊接工藝的應用&#xff0c;主要涉及氣保焊、電阻點焊、激光焊、電子束焊等多種焊接工藝。由于汽車車型眾多、成形結構復雜、汽車制造質量、效率、成本等方面的綜合要求。如何高效、…

杰理AC632N提升edr的hid傳輸速率, 安卓絕對坐標觸摸點被識別成鼠標的修改方法

第一個問題: 首先修改edr的hid傳輸速率.修改你的板級配置,里面的一個地方給注釋掉了,請打開那個注釋就能提升edr的hid傳輸效率了 第二個問題: 修改632n系別把觸摸板的hid報告描述符識別成鼠標點,修改如下: 注釋掉上面的pnp,改成下面的

element plus的容器組件

element-plus的容器組件主要有el-container,el-aside,el-header,el-main,el-footer,后面4個組件其父組件必須是el-container。 el-container采用flex布局&#xff0c;如果其子元素包含el-header或el-footer時會采用垂直布局&#xff0c;否則會采用水平布局&#xff0c;可設置其…

LeetCode|938. Range Sum of BST

. 序言 開啟python刷題時代&#xff0c;主要也是為了面試。 . 題目 Given the root node of a binary search tree and two integers low and high, return the sum of values of all nodes with a value in the inclusive range [low, high]. Example 1: Input: root …

教程 | Navicat 17 管理連接新方法

Navicat 17 提供了比以往更多的連接數據庫實例的方式。除了傳統的連接字符串方式以外&#xff0c;Navicat 17 還支持 URI 連接&#xff0c;無論身在何處&#xff0c;都可以輕松地通過 URI 訪問對象。另外&#xff0c;還有一個新的管理連接功能&#xff0c;即允許你通過一個以用…

大數據揭秘

起源 不管是國內&#xff0c;國外的招聘目前數據分析工程師&#xff0c;或者是大數據工程師我感覺都是處于啟蒙階段&#xff0c;對于數據分析或者大數據沒有什么體系技術棧一說&#xff0c;相比于前后端&#xff0c;除了高端互聯網企業其他的企業招數據分析工程師我認為目前都…

公有云服務器部署springboot工程詳細步驟

以下是在公有云服務器上部署Spring Boot工程的詳細步驟&#xff1a; 在公有云服務器上安裝Java運行環境&#xff1a;&#xff08;記得配置環境變量&#xff09; sudo apt update sudo apt install default-jre下載和部署Spring Boot工程&#xff1a; 將Spring Boot工程打包成可…

深入Maven:從入門到精通的全面指南

目錄 Maven簡介安裝MavenMaven的基本概念 項目對象模型&#xff08;POM&#xff09;依賴管理生命周期插件 Maven命令Maven倉庫Maven的構建生命周期Maven插件Maven與IDE的集成Maven高級主題 多模塊項目自定義插件開發使用profiles 常見問題與解決方案Maven的最佳實踐總結與參考…

后端大量數據返回,采用數據壓縮+分片操作,加快前端響應速度,個人技術總結

1. 業務場景 場景類似于&#xff0c;可以查看到這段時間內指定的所有物品的運動軌跡&#xff0c;可以進行回放操作。 2. 解決方案 2.1. 在不考慮壓縮的情況&#xff0c;可以盡可能減少傳輸數據的大小 比如 {[{"consDept":"A部門","consDeptCode&…

【全開源】房屋出租出售預約系統(FastAdmin+ThinkPHP+Uniapp)

房屋出租出售預約系統&#xff1a;一站式解決房產交易難題 一款基于FastAdminThinkPHPUniapp開發的房屋出租出售預約系統&#xff0c;支持小程序、H5、APP&#xff0c;包含房客、房東(高級授權)、經紀人(高級授權)三種身份。核心功能有&#xff1a;新盤銷售、房屋租賃、地圖找…

Python 技巧分享:NEF 文件的元數據提取

介紹 隨著攝影技術的不斷發展&#xff0c;NEF 文件作為尼康相機的 RAW 格式文件&#xff0c;因其包含豐富的圖像數據和元數據&#xff0c;備受攝影愛好者和專業攝影師的青睞。提取 NEF 文件中的元數據對照片管理、分析及處理具有重要意義。本文將介紹如何使用 Python 技術&…

慎投!Hindawi這本SCI還在檢,這里已被踢!新增14本Scopus期刊被剔除!

本周投稿推薦 SSCI ? 中科院2區&#xff0c;6.0-7.0&#xff08;錄用友好&#xff09; EI ? 各領域沾邊均可&#xff08;2天錄用&#xff09; CNKI ? 3天內初審錄用&#xff0c;隨即出版&#xff08;急錄友好&#xff09; SCI&EI ? 4區生物醫學類&#xff0c;0…

電商數據驅動的決策智慧:深度解析數據采集與應用||電商API接口接入與應用

引言 在數字化時代&#xff0c;數據已成為電商企業最寶貴的資產之一。通過有效的數據采集&#xff0c;企業能夠洞察市場動態、理解消費者需求、優化運營策略&#xff0c;從而在激烈的市場競爭中脫穎而出。本文將深入探討電商數據采集的重要性、常用方法以及應用實踐。 一、電商…

C語言—內存函數

1. memcpy 使用和模擬實現 void* memcpy&#xff08;void* destination&#xff0c;const void* source&#xff0c;size_t num&#xff09;&#xff1b; 函數memcpy從source的位置開始向后復制num個字節的數據到destination指向的內存位置。這個函數在遇到 ‘\0’ 的時候并不…

Docker 教程-介紹-2

快速了解docker有什么。 Docker簡介 Docker 是一個開源的應用容器引擎&#xff0c;基于Go語言開發&#xff0c;并遵循Apache 2.0協議。它允許開發者將應用及其依賴包打包進一個可移植的容器中&#xff0c;這些容器可以發布到任何支持Docker的Linux或Windows機器上&#xff0c…

神經網絡 torch.nn---Convolution Layers

torch.nn — PyTorch 2.3 documentation torch.nn - PyTorch中文文檔 (pytorch-cn.readthedocs.io) torch.nn和torch.nn.functional的區別 torch.nn是對torch.nn.functional的一個封裝&#xff0c;讓使用torch.nn.functional里面的包的時候更加方便 torch.nn包含了torch.nn.…

Linux日志服務rsyslog深度解析(上)

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《Linux &#xff1a;從菜鳥到飛鳥的逆襲》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、日志在Linux系統中的作用 2、rsyslog歷史背景 …

保姆級講解 FTP服務器的搭建、配置與管理

本來目錄很長的 因為感覺不太美觀 所以小標題都刪掉了 本文介紹了 本地用戶的FTP服務器搭建實例匿名用戶的FTP服務器搭建實例虛擬用戶的FTP服務器搭建實例企業常見類型搭建實驗 配置與管理FTP服務器 配置與管理FTP服務器一、FTP相關知識二、項目設計與準備三、項目實施四、認識…