cuda lib 線程安全的要義

1, 概述

cuda lib 線程安全的幾個多線程的情景:

單卡多線程;

多卡多線程-每卡單線程;

多卡多線程-每卡多線程;

需要考慮的問題:


每個 cublasHandle_t 只能有一個stream么?
每個cusolverHandle_t 只能有一個 stream么?
每個cusolverHandle_t只能有要給cublasHandle_t么?
多個線程同時跑在多個或一個gpu上,需要使用多個stream么?都是NULL 默認stream的話,不會影響效率吧?

2, 多線程示例

從如下代碼思考開去,這個多線程場景是使用了openmp自動劃分任務,也可以使用pthread來七分任務,這里對這個示例進行了注釋:

https://github.com/NVIDIA/cuda-samples/blob/v11.4/Samples/cudaOpenMP/cudaOpenMP.cu

/** Multi-GPU sample using OpenMP for threading on the CPU side* needs a compiler that supports OpenMP 2.0*/
//使用openmp時包含其頭文件
#include <omp.h>
#include <stdio.h>  // stdio functions are used since C++ streams aren't necessarily thread safe
//#include <helper_cuda.h>#define checkCudaErrors(val)  valusing namespace std;// a simple kernel that simply increments each array element by b
__global__ void kernelAddConstant(int *g_a, const int b)
{int idx = blockIdx.x * blockDim.x + threadIdx.x;g_a[idx] += b;
}// a predicate that checks whether each array element is set to its index plus 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;   // number of CUDA GPUsprintf("%s Starting...\n\n", argv[0]);/// determine the number of CUDA capable GPUs//cudaGetDeviceCount(&num_gpus);if (num_gpus < 1){printf("no CUDA capable devices were detected\n");return 1;}/// display CPU and GPU configuration//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);// nbytes = num_gpus * [8192*sizeof(int)]printf("nbytes=%u\n", nbytes);int *a = 0;     // pointer to data on the CPUint b = 3;      // value by which the array is incrementeda = (int *)malloc(nbytes);if (0 == a){printf("couldn't allocate CPU memory\n");return 1;}
//這里如果使用 #pragma omp parallel for 的話,會不會影響下面的線程數?for (unsigned int i = 0; i < n; i++)a[i] = i;// run as many CPU threads as there are CUDA devices//   each CPU thread controls a different device, processing its//   portion of the data.  It's possible to use more CPU threads//   than there are CUDA devices, in which case several CPU//   threads will be allocating resources and launching kernels//   on the same device.  For example, try omp_set_num_threads(2*num_gpus);//   Recall that all variables declared inside an "omp parallel" scope are//   local to each CPU thread//// 通過獲知GPU的數量來設定下面參與工作的線程數量omp_set_num_threads(num_gpus);  // create as many CPU threads as there are CUDA devices//omp_set_num_threads(2*num_gpus);// create twice as many CPU threads as there are CUDA devices//自動創建 num_gpus 個線程#pragma omp parallel{//每個線程獲得自己的線程號,從0開始計數unsigned int cpu_thread_id = omp_get_thread_num();//獲取 openmp 自動創建的總的線程數unsigned int num_cpu_threads = omp_get_num_threads();printf("cpu_thread_id=%u   num_cpu_threads=%u\n", cpu_thread_id, num_cpu_threads);// set and check the CUDA device for this CPU threadint gpu_id = -1;//兩個或以上的線程,可以同時使用同一個 gpu 設備;cudaSetDevice(id) 會使得本線程鎖定這個 id-th gpu 設備,接下來發生的cudaXXX,都是在這個gpu上發生的。checkCudaErrors(cudaSetDevice(cpu_thread_id % num_gpus));   // "% num_gpus" allows more CPU threads than GPU devicescheckCudaErrors(cudaGetDevice(&gpu_id));//這個函數僅僅返回本線程鎖定的gpu的id。printf("CPU thread %d (of %d) uses CUDA device %d, set id=%d, get id = %d\n", cpu_thread_id, num_cpu_threads, gpu_id, cpu_thread_id%num_gpus, gpu_id);int *d_a = 0;   // pointer to memory on the device associated with this CPU thread//下面找到本線程需要處理的數據起始地址int *sub_a = a + cpu_thread_id * n / num_cpu_threads;   // pointer to this CPU thread's portion of dataunsigned int nbytes_per_kernel = nbytes / num_cpu_threads;//其中的 nbytes = num_gpus * [8192*sizeof(int)], 是整除關系;得到每個線程需要分配的顯存字節數dim3 gpu_threads(128);  // 128 threads per blockdim3 gpu_blocks(n / (gpu_threads.x * num_cpu_threads));// n = num_gpus * 8192;   其中 8192 是128的整數倍, num_cpu_threads 是 num_gpus 的小小的整數倍; // 這樣每個block含128個線程; 每個線程需要幾個block呢 = n/(gpu_threads.x * num_cpu_threads)checkCudaErrors(cudaMalloc((void **)&d_a, nbytes_per_kernel));//在本線程所setDevice的gpu上cudaMalloc顯存空間;checkCudaErrors(cudaMemset(d_a, 0, nbytes_per_kernel));//將分的的空間刷0// 將本線程需要處理的數據塊拷貝的本線程所cudaMalloc的顯存中;checkCudaErrors(cudaMemcpy(d_a, sub_a, nbytes_per_kernel, cudaMemcpyHostToDevice));//本線程啟動kernel,處理自己的顯存的數據;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 memoryexit(bResult ? EXIT_SUCCESS : EXIT_FAILURE);
}


運行效果:


要保證cuda lib的線程安全,首先確定cuda driver cuda runtime 都是線程安全的,這個其實是沒有問題的,也就是說多個線程多塊顯卡同時運行的場景是不會引發cuda runtime的線程安全問題的,這點可以放心;

3, 多線程安全分析

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

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

相關文章

python3.5安裝教程及環境配置,python3.7.2安裝與配置

大家好&#xff0c;小編來為大家解答以下問題&#xff0c;python3.5安裝教程及環境配置&#xff0c;python3.7.2安裝與配置&#xff0c;現在讓我們一起來看看吧&#xff01; python 從爬蟲開始&#xff08;一&#xff09; Python 簡介 首先簡介一下Python和爬蟲的關系與概念&am…

Android Studio的代碼筆記--IntentService學習

IntentService學習 IntentService常規用法清單注冊服務服務內容開啟服務 IntentService 一個 HandlerThread工作線程&#xff0c;通過Handler實現把消息加入消息隊列中等待執行&#xff0c;通過傳遞的intent在onHandleIntent中處理任務。&#xff08;多次調用會按順序執行事件…

Spring Cloud Alibaba實踐 --Sentinel

sentinel簡介 Sentinel的官方標題是&#xff1a;分布式系統的流量防衛兵。從名字上來看&#xff0c;很容易就能猜到它是用來作服務穩定性保障的。對于服務穩定性保障組件&#xff0c;如果熟悉Spring Cloud的用戶&#xff0c;第一反應應該就是Hystrix。但是比較可惜的是Netflix…

三防平板|手持終端PDA|8寸/10寸工業三防平板電腦主板方案定制

近年來&#xff0c;隨著科技的快速發展&#xff0c;三防平板成為了各行各業中不可或缺的工具。三防平板采用IP67級別的防護設計&#xff0c;通過了多項測試標準&#xff0c;如國標和美標&#xff0c;具備防水、防摔、防塵、防撞、防震、防跌落以及防鹽霧等多重防護功能。因此&a…

JavaScript 簡單理解原型和創建實例時 new 操作符的執行操作

function Person(){// 構造函數// 當函數創建&#xff0c;prototype 屬性指向一個原型對象時&#xff0c;在默認情況下&#xff0c;// 這個原型對象將會獲得一個 constructor 屬性&#xff0c;這個屬性是一個指針&#xff0c;指向 prototype 所在的函數對象。 } // 為原型對象添…

HarmonyOS應用開發工具DevEco Studio安裝與使用

語雀知識庫地址&#xff1a;語雀HarmonyOS知識庫 飛書知識庫地址&#xff1a;飛書HarmonyOS知識庫 知識庫內容逐步完善中… 工欲善其事必先利其器&#xff0c;要編寫HarmonyOS應用就需要用到官方提供的IDE工具來編寫相應的代碼。 在鴻蒙開發者官網&#xff0c;其提供了官方的開…

基于Java醫院掛號管理系統

基于Java醫院掛號管理系統 功能需求 1、患者信息管理&#xff1a;系統需要提供患者的基本信息錄入功能&#xff0c;包括姓名、性別、年齡、聯系方式等。此外&#xff0c;系統還應支持對患者信息進行修改、查詢和刪除的操作。 2、掛號管理&#xff1a;系統需要提供掛號功能&a…

高效的多維空間點索引算法——GeoHash

一、Geohash 算法簡介 GeoHash是空間索引的一種方式&#xff0c;其基本原理是將地球理解為一個二維平面&#xff0c;通過把二維的空間經緯度數據編碼為一個字符串&#xff0c;可以把平面遞歸分解成更小的子塊&#xff0c;每個子塊在一定經緯度范圍內擁有相同的編碼。以GeoHash方…

springboot 極簡案例

安裝idea File -> New Project 選擇依賴 創建controller文件 輸入controller類名 輸入代碼 運行項目 訪問 localhost:8080/hello/boot package com.example.demo;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.…

數據庫對象介紹與實踐:視圖、函數、存儲過程、觸發器和物化視圖

文章目錄 一、視圖&#xff08;View&#xff09;1、概念2、基本操作1&#xff09;創建視圖2&#xff09;修改視圖3&#xff09;刪除視圖4&#xff09;使用視圖 3、使用場景4、實踐 二、函數&#xff08;Function&#xff09;1、概念2、基本操作1&#xff09;創建函數2&#xff…

粵能環保亮相迪拜COP28,智能技術鑄就運河城市可持續未來

在全球應對氣候變化的重要會議——迪拜COP28大會上&#xff0c;運河城市面臨的獨特環境挑戰引起了廣泛關注。隨著城市化進程的加快&#xff0c;運河城市在處理固體廢物、減少溫室氣體排放以及維持水資源安全方面面臨著嚴峻考驗。智能垃圾分類作為應對這些挑戰的有效途徑&#x…

一些系統日常運維命令和語句

一、前言 記錄一些日常系統運維的命令和語句 二、linux命令與語句 1、linux查看各目錄使用磁盤情況 du -h /home home為目錄 du -h /home 2.查看內存使用情況 free -h 3、查看進程和CPU使用情況 top top 三、數據庫語句 1、統計mysql數據庫表數量 SELECT COUNT(*) A…

被動副業機賺錢項目教程,Docker一鍵安裝教程

被動副業機賺錢項目教程&#xff0c;Docker一鍵安裝教程 Docker一鍵運行 軟件下載 視頻教程 /opt/wxedge_storage 路徑換成你設備里面的路徑即可&#xff0c;其余參數不用變&#xff0c; 鏡像名為onething1/wxedge 更多安裝說明&#xff0c;可參考官方文檔&#xff1a;容器魔…

【算法每日一練]-結構優化(保姆級教程 篇4 樹狀數組,線段樹,分塊模板篇)

目錄 分塊 分塊算法步驟&#xff1a; 樹狀數組 樹狀數組步驟&#xff1a; 線段樹點更新 點更新步驟&#xff1a; 線段樹區間更新 區間更新步驟&#xff1a; 不同于倍增和前綴和與差分序列。 前綴和處理不更新的區間和 差分處理離線的區間更新問題 倍增處理離線的區間…

C++的繼承語法

在面向對象編程中&#xff0c;繼承是一種強大的機制&#xff0c;允許一個類&#xff08;子類&#xff09;從另一個類&#xff08;父類&#xff09;繼承屬性和方法。C是一種支持面向對象編程的編程語言&#xff0c;通過其靈活而強大的繼承語法&#xff0c;開發者可以構建更加模塊…

維普論文查重率高【詳細說明】

大家好&#xff0c;今天來聊聊維普論文查重率高&#xff0c;希望能給大家提供一點參考。 以下是針對論文重復率高的情況&#xff0c;提供一些修改建議和技巧&#xff1a; 維普論文查重率高&#xff1a;原因分析與降重技巧 背景介紹 在學術領域&#xff0c;論文的重復率是衡量其…

老電腦重置后能連上WIFI但是打開360網頁老是提示該網址不是私密連接

看了一下可以忽略這次提示&#xff0c;能夠上網&#xff0c;但是每次打開新網頁都會有“該網址不是私密連接”提示&#xff0c;這個提示非常大&#xff0c;嚴重影響上網。 強行下載了谷歌瀏覽器并打開后&#xff0c;提示“您的時鐘慢了”&#xff0c;然后看了一下電腦右下角日期…

CLion手把手教你創建Windows項目

作為一個Jetbrains迷的我&#xff0c;下載了Jetbrains全家桶&#xff0c;我就想用CLion 編寫 Windows 項目 前提&#xff1a;必須安裝 Visual Studio 2022 New Project 選擇 C Executable&#xff0c;取好項目名&#xff0c; 點擊 Create 在 CMakeList.txt 中添加以下內容&…

系列八、SpringBoot中自定義SpringMVC配置

一、概述 作為Spring家族的明星產品&#xff0c;SpringBoot極大地簡化了程序員的日常開發&#xff0c;提高了開發效率。我們很容易得借助于SpringBoot就可以快速開發業務代碼。一般情況下&#xff0c;公司的日常開發都是基于web服務的&#xff0c;我們在使用idea等工具初始化一…

Zabbix補充

Zabbix的自動發現機制&#xff1a; Zabbix客戶端主動和服務端聯系&#xff0c;將自己的地址和端口發送服務端&#xff0c;來實現自動添加主機 客戶端是自動的一方 缺點&#xff1a;自定義的網段的主機數量太多&#xff0c;登記耗時會很久&#xff0c;而且這個自動發現機制不是…