Configuración del hilo de programación de la GPU

1. Estructura de la composición del hilo

La estructura específica se puede dividir en: Cuadrícula-> Bloque-> Deformar -> hilo de arriba a abajo.

Grid / Block / Warp / Thread son todas estructuras de organización de software, no hardware, por lo que teóricamente podemos organizar los hilos en cualquier dimensión (unidimensional, bidimensional, tridimensional); en el hardware, es solo un SP, hay no existe la dimensionalidad, pero el concepto de dimensionalidad se abstrae del software.

Warp es el tercer nivel de la estructura, con 32 hilos como grupo.

Inserte la descripción de la imagen aquí

2. Determine la configuración de su tarjeta gráfica.

Antes de programar, debe tenerse en cuenta que la cantidad de subprocesos y bloques admitidos por la tarjeta gráfica es limitada. Por lo tanto, primero confirme la configuración de la tarjeta gráfica. De lo contrario, una vez que el programa exceda el límite de hardware de la tarjeta gráfica, dejará de funcionar.

Rutinas CUDA para imprimir la configuración de la tarjeta gráfica:

/***
 *打印显卡属性
 *2017-11-8
 * ***/

#include<iostream>
#include <cuda_runtime.h>
#include<device_launch_parameters.h>

using namespace std;

int main()
{
    
    
	int deviceCount;

	cudaGetDeviceCount(&deviceCount);	//Returns in *deviceCount the number of devices
	cout << "deviceCount:   " << deviceCount << "\n\n";
	if (deviceCount == 0)
	{
    
    
		cout << "error: no devices supporting CUDA.\n";
		exit(EXIT_FAILURE);
	}

	int dev = 0;
	cudaSetDevice(dev);	//Sets dev=0 device as the current device for the calling host thread.

	cudaDeviceProp devProps;
	cudaGetDeviceProperties(&devProps, dev);

	cout << "name: " << devProps.name << "\n";
	cout << "totalGlobalMem: " << devProps.totalGlobalMem << "\n";
	cout << "regsPerBlock: " << devProps.regsPerBlock << "\n";
	cout << "warpSize: " << devProps.warpSize << "\n";
	cout << "memPitch: " << devProps.memPitch << "\n\n";

	cout << "一个线程块中可使用的最大共享内存\n";
	cout << "devProps.sharedMemPerBlock: " << devProps.sharedMemPerBlock << "\n\n";

	cout << "一个线程块中可包含的最大线程数量\n";
	cout << "maxThreadsPerBlock: " << devProps.maxThreadsPerBlock << "\n\n";

	cout << "多维线程块数组中每一维可包含的最大线程数量\n";
	cout << "maxThreadsDim[0]: " << devProps.maxThreadsDim[0] << "\n";
	cout << "maxThreadsDim[1]: " << devProps.maxThreadsDim[1] << "\n";
	cout << "maxThreadsDim[2]: " << devProps.maxThreadsDim[2] << "\n\n";

	cout << "一个线程格中每一维可包含的最大线程块数量\n";
	cout << "maxGridSize[0]: " << devProps.maxGridSize[0] << "\n";
	cout << "maxGridSize[1]: " << devProps.maxGridSize[1] << "\n";
	cout << "maxGridSize[2]: " << devProps.maxGridSize[2] << "\n\n";

	cout << "clockRate: " << devProps.clockRate << "\n";
	cout << "totalConstMem: " << devProps.totalConstMem << "\n";
	cout << "textureAlignment: " << devProps.textureAlignment << "\n\n";

	cout << "计算能力:" << devProps.major << "." << devProps.minor << "\n\n";

	cout << "minor: " << devProps.minor << "\n";
	cout << "texturePitchAlignment: " << devProps.texturePitchAlignment << "\n";
	cout << "deviceOverlap: " << devProps.deviceOverlap << "\n";
	cout << "multiProcessorCount: " << devProps.multiProcessorCount << "\n";
	cout << "kernelExecTimeoutEnabled: " << devProps.kernelExecTimeoutEnabled << "\n";
	cout << "integrated: " << devProps.integrated << "\n";
	cout << "canMapHostMemory: " << devProps.canMapHostMemory << "\n";
	cout << "computeMode: " << devProps.computeMode << "\n";
	cout << "maxTexture1D: " << devProps.maxTexture1D << "\n";
	cout << "maxTexture1DMipmap: " << devProps.maxTexture1DMipmap << "\n";
	cout << "maxTexture1DLinear: " << devProps.maxTexture1DLinear << "\n";
	cout << "maxTexture2D: " << devProps.maxTexture2D << "\n";
	cout << "maxTexture2DMipmap: " << devProps.maxTexture2DMipmap << "\n";
	cout << "maxTexture2DLinear: " << devProps.maxTexture2DLinear << "\n";
	cout << "maxTexture2DGather: " << devProps.maxTexture2DGather << "\n";
	cout << "maxTexture3D: " << devProps.maxTexture3D << "\n";
	cout << "maxTexture3DAlt: " << devProps.maxTexture3DAlt << "\n";
	cout << "maxTextureCubemap: " << devProps.maxTextureCubemap << "\n";
	cout << "maxTexture1DLayered: " << devProps.maxTexture1DLayered << "\n";
	cout << "maxTexture2DLayered: " << devProps.maxTexture2DLayered << "\n";
	cout << "maxTextureCubemapLayered: " << devProps.maxTextureCubemapLayered << "\n";
	cout << "maxSurface1D: " << devProps.maxSurface1D << "\n";
	cout << "maxSurface2D: " << devProps.maxSurface2D << "\n";
	cout << "maxSurface3D: " << devProps.maxSurface3D << "\n";
	cout << "maxSurface1DLayered: " << devProps.maxSurface1DLayered << "\n";
	cout << "maxSurface2DLayered: " << devProps.maxSurface2DLayered << "\n";
	cout << "maxSurfaceCubemap: " << devProps.maxSurfaceCubemap << "\n";
	cout << "maxSurfaceCubemapLayered: " << devProps.maxSurfaceCubemapLayered << "\n";
	cout << "surfaceAlignment: " << devProps.surfaceAlignment << "\n";
	cout << "concurrentKernels: " << devProps.concurrentKernels << "\n";
	cout << "ECCEnabled: " << devProps.ECCEnabled << "\n";
	cout << "pciBusID: " << devProps.pciBusID << "\n";
	cout << "pciDeviceID: " << devProps.pciDeviceID << "\n";
	cout << "pciDomainID: " << devProps.pciDomainID << "\n";
	cout << "tccDriver: " << devProps.tccDriver << "\n";
	cout << "asyncEngineCount: " << devProps.asyncEngineCount << "\n";
	cout << "unifiedAddressing: " << devProps.unifiedAddressing << "\n";
	cout << "memoryClockRate: " << devProps.memoryClockRate << "\n";
	cout << "memoryBusWidth: " << devProps.memoryBusWidth << "\n";
	cout << "l2CacheSize: " << devProps.l2CacheSize << "\n";
	cout << "maxThreadsPerMultiProcessor: " << devProps.maxThreadsPerMultiProcessor << "\n";
	cout << "streamPrioritiesSupported: " << devProps.streamPrioritiesSupported << "\n";
	cout << "globalL1CacheSupported: " << devProps.globalL1CacheSupported << "\n";
	cout << "localL1CacheSupported: " << devProps.localL1CacheSupported << "\n";
	cout << "sharedMemPerMultiprocessor: " << devProps.sharedMemPerMultiprocessor << "\n";
	cout << "regsPerMultiprocessor: " << devProps.regsPerMultiprocessor << "\n";
	cout << "isMultiGpuBoard: " << devProps.isMultiGpuBoard << "\n";
	cout << "multiGpuBoardGroupID: " << devProps.multiGpuBoardGroupID << "\n";
	cout << "singleToDoublePrecisionPerfRatio: " << devProps.singleToDoublePrecisionPerfRatio << "\n";
	cout << "pageableMemoryAccess: " << devProps.pageableMemoryAccess << "\n";
	cout << "concurrentManagedAccess: " << devProps.concurrentManagedAccess << "\n";

	return 0;
}

Inserte la descripción de la imagen aquí

3. Parámetros de la función del núcleo de CUDA (función del núcleo)

Comprender las tareas que realizan los subprocesos en la programación de GPU.

/*
kernel函数的样例
*/
// CUDA核函数的定义
__global__ void addKernel(int *c, const int *a, const int *b)
{
    
    
    int i = threadIdx.x;
    c[i] = a[i] + b[i];
}

// CUDA核函数调用
addKernel<<<Dg,Db, Ns, S>>>(c, a, b);

Es necesario prestar atención a los siguientes puntos:
1. El logo " global " antes de la función indica que la función se ejecuta en la GPU.
2. Cuando se llama a la función, el número de subprocesos debe determinarse mediante <<< >>>.
3. El significado de cada parámetro al llamar a la función del kernel:
Dg : tipo int o tipo dim3 (x, y, z), se usa para definir cómo se organizan los bloques en un Grid, si es un tipo int, significa un estructura organizativa unidimensional
Db : tipo Int o tipo dim3 (x, y, z), utilizado para definir cómo se organiza el Thread en un bloque, si es de tipo int, significa una estructura organizativa unidimensional
Ns : size_t tipo, puede ser predeterminado, el valor predeterminado es 0; Se utiliza para establecer el tamaño máximo de memoria compartida que se puede asignar dinámicamente para cada bloque además de la memoria compartida asignada estáticamente, en bytes. 0 significa que no se requiere asignación dinámica.
S : tipo cudaStream_t, puede ser predeterminado, el valor predeterminado es 0. Indica en qué secuencia se encuentra la función del kernel.

3.1 Cuadrícula 1d 和 Bloque 1d

El modo de llamada de cuda:
La siguiente figura muestra que una cuadrícula tiene 4 bloques de bloques (números: 0-3) y un bloque de bloques tiene 8 subprocesos (números: 0-7).

kernel_name<<<4, 8>>>(...)

El método de cálculo del índice de hilo en la función principal de cuda es el siguiente:

int threadId = blockIdx.x * blockDim.x + threadIdx.x 

3.2 Cuadrícula 2d 和 Bloque 2d

La forma de calcular el índice para dimensiones altas es similar a calcular el número de datos en una matriz multidimensional. Es necesario calcular el número de subprocesos en todos los bloques delante del subproceso y agregar el número de serie del subproceso en este bloque.

Formulario de llamada:

dim3 grid(4,1), block(2,2);
kernel_name<<<grid, block>>>(...)

Método de cálculo del índice:

int x = threadIdx.x + blockIdx.x * blockDim.x; 
int y = threadIdx.y + blockIdx.y * blockDim.y;
int offset = x + y * blockDim.x * gridDim.x; 

o

int blockId = blockIdx.x + blockId.y * gridDim.x;
int threadId = blockId * (blockDim.x * blockDim.y) + (threadIdx.y * blockDim.x) + threadIdx.x;

Nota : En la clasificación bidimensional, Thread (0,1) representa el Thread en la fila 1, columna 0, que no es lo mismo que la abscisa y ordenada en nuestro entendimiento tradicional; definimos la cuadrícula (4,2) para representar la primera Una dimensión tiene 4 valores de índice y la segunda dimensión tiene 2 valores de índice, es decir, 2 filas y 4 columnas.
Inserte la descripción de la imagen aquí
Nota : dim3 es un tipo de vector entero personalizado en la programación CUDA de NVIDIA, basado en uint3 para especificar dimensiones.

P.ej:

dim3 grid(num1,num2,num3);

La configuración final del tipo dim3 es un vector tridimensional, los parámetros tridimensionales son x, y, z;

3.3 Cuadrícula 3d 和 Bloque 3d

3d es relativamente raro y su fórmula de cálculo de subprocesos es la siguiente:

int blockId = blockIdx.x + blockIdx.y * gridDim.x + gridDim.x * gridDim.y * blockIdx.z;
int threadIc = blockId * (blockDim.x * blockDim.y * blockDim.z) 
                       + (threadIdx.z * (blockDim.x * blockDim.y)) 
                       + (threadIdx.y * blockDim.x) + threadIdx.x;   

3.4 Resumen de fórmulas de cálculo

Bloque unidimensional de cuadrícula unidimensional

blockId = blockIdx.x 
threadId = blockIdx.x *blockDim.x + threadIdx.x

Bloque bidimensional de cuadrícula unidimensional

blockId = blockIdx.x 
threadId = blockIdx.x * blockDim.x * blockDim.y + threadIdx.y * blockDim.x + threadIdx.x

Bloque tridimensional de cuadrícula unidimensional

blockId = blockIdx.x 
threadId = blockIdx.x * blockDim.x * blockDim.y * blockDim.z 
                        + threadIdx.z * blockDim.y * blockDim.x 
                        + threadIdx.y * blockDim.x + threadIdx.x

Bloque unidimensional de cuadrícula bidimensional

int blockId = blockIdx.y * gridDim.x + blockIdx.x;  
int threadId = blockId * blockDim.x + threadIdx.x;

Bloque bidimensional de cuadrícula bidimensional

int blockId = blockIdx.x + blockIdx.y * gridDim.x;  
int threadId = blockId * (blockDim.x * blockDim.y) 
                       + (threadIdx.y * blockDim.x) + threadIdx.x;  

Bloque 3D de cuadrícula 2D

int blockId = blockIdx.x + blockIdx.y * gridDim.x;  
int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)  
                       + (threadIdx.z * (blockDim.x * blockDim.y))  
                       + (threadIdx.y * blockDim.x) + threadIdx.x;

Bloque unidimensional de cuadrícula tridimensional

int blockId = blockIdx.x + blockIdx.y * gridDim.x + gridDim.x * gridDim.y * blockIdx.z;  
int threadId = blockId * blockDim.x + threadIdx.x;  

Bloque 2D de cuadrícula 3D

int blockId = blockIdx.x + blockIdx.y * gridDim.x + gridDim.x * gridDim.y * blockIdx.z;  
int threadId = blockId * (blockDim.x * blockDim.y) 
                       + (threadIdx.y * blockDim.x) + threadIdx.x; 

Bloque 3D de cuadrícula 3D

int blockId = blockIdx.x + blockIdx.y * gridDim.x + gridDim.x * gridDim.y * blockIdx.z;  
int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)  
                       + (threadIdx.z * (blockDim.x * blockDim.y))  
                       + (threadIdx.y * blockDim.x) + threadIdx.x;

Supongo que te gusta

Origin blog.csdn.net/daijingxin/article/details/109017574
Recomendado
Clasificación