亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

CUDA中block和thread的合理劃分配置

2019-11-14 11:35:13
字體:
來源:轉載
供稿:網友

CUDA并行編程的基本思路是把一個很大的任務劃分成N個簡單重復的操作,創建N個線程分別執行執行,每個網格(Grid)可以最多創建65535個線程塊,每個線程塊(Block)一般最多可以創建512個并行線程,在第一個CUDA程序中對核函數的調用是:

addKernel<<<1, size>>>(dev_c, dev_a, dev_b);

這里的<<<>>>運算符內是核函數的執行參數,告訴編譯器運行時如何啟動核函數,用于說明內核函數中的線程數量,以及線程是如何組織的。

<<<>>>運算符完整的執行配置參數形式是<<<Dg, Db, Ns, S>>>

參數Dg用于定義整個grid的維度和尺寸,即一個grid有多少個block。為dim3類型。Dim3 Dg(Dg.x, Dg.y, 1)表示grid中每行有Dg.x個block,每列有Dg.y個block,第三維恒為1(目前一個核函數只有一個grid)。整個grid中共有Dg.x*Dg.y個block,其中Dg.x和Dg.y最大值為65535。參數Db用于定義一個block的維度和尺寸,即一個block有多少個thread。為dim3類型。Dim3 Db(Db.x, Db.y, Db.z)表示整個block中每行有Db.x個thread,每列有Db.y個thread,高度為Db.z。Db.x和Db.y最大值為512,Db.z最大值為62。 一個block中共有Db.x*Db.y*Db.z個thread。計算能力為1.0,1.1的硬件該乘積的最大值為768,計算能力為1.2,1.3的硬件支持的最大值為1024。參數Ns是一個可選參數,用于設置每個block除了靜態分配的shared Memory以外,最多能動態分配的shared memory大小,單位為byte。不需要動態分配時該值為0或省略不寫。參數S是一個cudaStream_t類型的可選參數,初始值為零,表示該核函數處在哪個流之中。在第一個CUDA程序中使用了1個線程塊,每個線程塊包含size個并行線程,每個線程的索引是threadIdx.x。也可以選擇創建size個線程塊,每個線程塊包含1個線程,核函數的調用更改為:addKernel<<<size, 1>>>(dev_c, dev_a, dev_b);線程的索引更改為blockIdx.x。完整程序如下:
#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 = blockIdx.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;	}	getchar();	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);	addKernel << <size, 1 >> > (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;}執行結果一致:更普遍的情況是需要創建多個線程塊,每個線程塊包含多個并行線程,這種情況下線程索引的計算為:int tid=threadIdx.x+blockIdx.x*blockDim.x;blockIdx代表線程塊在網格中的索引值,blockDim代表線程塊的尺寸大小,另外還有gridDim代表網格的尺寸大小。如果有N個并行的任務,我們希望每個線程塊固定包含6個并行的線程,則可以使用以下的核函數調用:addKernel<<<(N+5)/6, 6>>>(dev_c, dev_a, dev_b);把第一個CUDA程序的向量個數增加到15個,修改成以上調用方式:
#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 + blockIdx.x*blockDim.x;	if (i < 15)		c[i] = a[i] + b[i];}int main(){	const int arraySize = 15;	const int a[arraySize] = { 1, 2, 3, 4, 5,6,7,8,9,10,11,12,13,14,15 };	const int b[arraySize] = { 10, 20, 30, 40, 50,60,70,80,90,100,110,120,130,140,150 };	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,6,7,8,9,10,11,12,13,14,15}+/n{ 10, 20, 30, 40, 50,60,70,80,90,100,110,120,130,140,150}=/n{%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d}/n",		c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13], c[14]);	// 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;	}	getchar();	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);	addKernel << <(size + 5) / 6, 6 >> > (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;}執行結果:以下CUDA和OpenCV混合編程,對一幅圖像上每個像素點的顏色執行一次運算,生成一幅規則的圖形。新建了一個 dim3類型的變量grid(DIM, DIM),代表一個二維的網格,尺寸大小是DIM*DIM個線程塊:
#include "cuda_runtime.h"  #include <highgui.hpp>  using namespace cv;#define DIM 600   //圖像長寬  __global__ void kernel(unsigned char *ptr){	// map from blockIdx to pixel position  	int x = blockIdx.x;	int y = blockIdx.y;	int offset = x + y * gridDim.x;	//BGR設置	ptr[offset * 3 + 0] = 999 * x*y % 255;	ptr[offset * 3 + 1] = 99 * x*x*y*y % 255;	ptr[offset * 3 + 2] = 9 * offset*offset % 255;}// globals needed by the update routine  struct DataBlock{	unsigned char   *dev_bitmap;};int main(void){	DataBlock   data;	cudaError_t error;	Mat image = Mat(DIM, DIM, CV_8UC3, Scalar::all(0));	data.dev_bitmap = image.data;	unsigned char    *dev_bitmap;	error = cudaMalloc((void**)&dev_bitmap, 3 * image.cols*image.rows);	data.dev_bitmap = dev_bitmap;	dim3    grid(DIM, DIM);	//DIM*DIM個線程塊	kernel <<<grid, 1 >>> (dev_bitmap);	error = cudaMemcpy(image.data, dev_bitmap,		3 * image.cols*image.rows,		cudaMemcpyDeviceToHost);	error = cudaFree(dev_bitmap);	imshow("CUDA Grid/Block/Thread)", image);	waitKey();}執行效果:


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩在线精品一区| 欧美麻豆久久久久久中文| 亚洲国产精品悠悠久久琪琪| 在线观看精品自拍私拍| 在线观看国产欧美| 精品在线小视频| 国产一区在线播放| 在线视频精品一| 国产色视频一区| 亚洲美女www午夜| 欧美巨猛xxxx猛交黑人97人| 九九热这里只有精品6| 成人黄色影片在线| 亚洲综合色av| 亚洲a在线播放| 精品久久久久久久久久| 日韩成人av网址| 日韩精品免费在线视频| 欧美成人免费网| 成人两性免费视频| 亚洲男人天堂网站| 成人在线视频网站| 午夜精品视频网站| 亚洲美女中文字幕| 久久成人精品视频| 91久久精品一区| 欧美日韩国产一区在线| 在线观看免费高清视频97| 精品久久久久久久久久久| 国产精品一区二区久久久久| 欧美黑人国产人伦爽爽爽| 精品久久久免费| 国产精品一香蕉国产线看观看| 一区二区亚洲精品国产| 大伊人狠狠躁夜夜躁av一区| 日韩精品在线观看一区| 少妇高潮 亚洲精品| 影音先锋欧美精品| 欧美在线视频一二三| 国产日韩在线播放| 欧美国产日本高清在线| 萌白酱国产一区二区| 国产精品久久久久久久久免费看| 亚洲一区二区三区视频| 欧美亚洲国产另类| 91国产一区在线| 国内免费久久久久久久久久久| 久久中文字幕一区| 国产婷婷97碰碰久久人人蜜臀| 欧美肥老太性生活视频| 久久久国产精品x99av| 久久99精品久久久久久噜噜| 国产精品视频1区| 美女啪啪无遮挡免费久久网站| 国产亚洲一区二区精品| 亚洲国产精品va在线观看黑人| 日韩精品中文在线观看| 精品国产自在精品国产浪潮| 成人欧美在线观看| 久久精品电影网站| 亚洲人高潮女人毛茸茸| 亚洲成人黄色网| 欧美最猛性xxxxx免费| 亚洲高清色综合| 日本精品一区二区三区在线| 日韩欧美亚洲范冰冰与中字| 国产高清视频一区三区| 中文字幕精品久久| 亚洲国产中文字幕久久网| 亚洲无限乱码一二三四麻| 亚洲女在线观看| 91精品国产综合久久男男| 亚洲一区二区三区毛片| 欧美日韩国产一区中文午夜| 成人激情视频免费在线| 亚洲自拍偷拍在线| 欧美电影免费观看| 日韩国产精品亚洲а∨天堂免| 亚洲精品日韩久久久| 日韩电影中文 亚洲精品乱码| 欧美高清一级大片| 精品国产视频在线| 久久精品91久久久久久再现| 精品中文视频在线| 日韩三级影视基地| 欧美精品日韩三级| 久久亚洲私人国产精品va| 国产精品尤物福利片在线观看| 一区二区在线视频播放| 亚洲欧美一区二区三区在线| 国产精品成久久久久三级| 亚洲国产一区二区三区四区| 久久九九亚洲综合| 国产精品自产拍在线观看中文| 久久九九亚洲综合| 日韩一区二区三区在线播放| 亚洲乱码国产乱码精品精天堂| 一区二区三区久久精品| 国产精品视频网址| 国产成人精品a视频一区www| 久久91超碰青草是什么| 亚洲激情免费观看| 美女av一区二区| 亚洲xxxxx| 国产裸体写真av一区二区| 中文字幕精品在线| 亚洲深夜福利网站| 国产精品免费观看在线| 日韩麻豆第一页| 日韩成人在线观看| 97精品视频在线| 日韩国产精品亚洲а∨天堂免| 97精品欧美一区二区三区| 国产一区二区三区视频| 日韩久久免费电影| 国产一区玩具在线观看| 日本精品免费观看| 黑人巨大精品欧美一区二区免费| 精品中文字幕乱| 欧美日韩一区二区三区在线免费观看| 亚洲福利精品在线| 69视频在线播放| 欧美日韩亚洲国产一区| 色婷婷久久一区二区| 国产日韩欧美91| 8x海外华人永久免费日韩内陆视频| 精品国产福利视频| 精品动漫一区二区三区| 国产精品久久久av| 日本午夜精品理论片a级appf发布| 成人在线激情视频| 国产精品久久久久久久一区探花| 亚洲字幕一区二区| 2020国产精品视频| 国产精品福利无圣光在线一区| 国产精品网址在线| 美女视频黄免费的亚洲男人天堂| 欧美极品少妇全裸体| 精品久久久久久久久久久久久| 91免费精品视频| 中文字幕视频在线免费欧美日韩综合在线看| 黑人极品videos精品欧美裸| 欧美一级片在线播放| 精品国产乱码久久久久久天美| 久久免费视频网| 亚洲欧美日韩精品久久奇米色影视| 日韩在线小视频| 性色av一区二区三区红粉影视| 欧美午夜电影在线| 日韩经典一区二区三区| 日韩中文字幕在线视频播放| 欧美自拍视频在线观看| 久久亚洲国产成人| 91久久精品久久国产性色也91| 91久久久精品| 97视频在线观看免费高清完整版在线观看| 成人综合网网址| 91沈先生在线观看| 狠狠躁夜夜躁人人爽天天天天97| 97国产成人精品视频| 欧美激情乱人伦| 国产成人在线亚洲欧美| 欧美亚洲国产视频| 亚洲精品久久7777777|