J'ai un simple noyau de multiplication vectorielle, que j'exécute pour 2 flux. Mais quand je profile dans NVVP, les noyaux ne semblent pas se chevaucher. Est-ce parce que chaque exécution de noyau utilise% 100 de GPU, sinon quelle peut être la cause?Les noyaux CUDA ne se chevauchent pas
code source:
#include "common.h"
#include <cstdlib>
#include <stdio.h>
#include <math.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "cuda_profiler_api.h"
#include <string.h>
const int N = 1 << 20;
__global__ void kernel(int n, float *x, float *y)
{
int i = blockIdx.x*blockDim.x + threadIdx.x;
if (i < n) y[i] = x[i] * y[i];
}
int main()
{
float *x, *y, *d_x, *d_y, *d_1, *d_2;
x = (float*)malloc(N*sizeof(float));
y = (float*)malloc(N*sizeof(float));
cudaMalloc(&d_x, N*sizeof(float));
cudaMalloc(&d_y, N*sizeof(float));
cudaMalloc(&d_1, N*sizeof(float));
cudaMalloc(&d_2, N*sizeof(float));
for (int i = 0; i < N; i++) {
x[i] = 1.0f;
y[i] = 2.0f;
}
cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_1, x, N*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_2, y, N*sizeof(float), cudaMemcpyHostToDevice);
const int num_streams = 8;
cudaStream_t stream1;
cudaStream_t stream2;
cudaStreamCreateWithFlags(&stream1, cudaStreamNonBlocking);
cudaStreamCreateWithFlags(&stream2, cudaStreamNonBlocking);
cudaEvent_t start, stop;
float elapsedTime;
cudaEventCreate(&start);
cudaEventRecord(start, 0);
for (int i = 0; i < 300; i++) {
kernel << <512, 512, 0, stream1 >> >(N, d_x, d_y);
kernel << <512, 512, 0, stream2 >> >(N, d_1, d_2);
}
cudaStreamSynchronize(stream1);
cudaStreamSynchronize(stream2);
// cudaDeviceSynchronize();
cudaEventCreate(&stop);
cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&elapsedTime, start, stop);
printf("Elapsed time : %f ms\n", elapsedTime);
cudaDeviceReset();
cudaProfilerStop();
return 0;
}
EDIT: D'après les commentaires que je comprends chaque noyau est en utilisant pleinement GPU, alors quelle est la meilleure approche pour atteindre 262144 taille multiplication du vecteur (pour plusieurs cours d'eau) ?
Mes informations sur le périphérique:
CUDA Device Query...
There are 1 CUDA devices.
CUDA Device #0
Major revision number: 5
Minor revision number: 0
Name: GeForce GTX 850M
Total global memory: 0
Total shared memory per block: 49152
Total registers per block: 65536
Warp size: 32
Maximum memory pitch: 2147483647
Maximum threads per block: 1024
Maximum dimension 0 of block: 1024
Maximum dimension 1 of block: 1024
Maximum dimension 2 of block: 64
Maximum dimension 0 of grid: 2147483647
Maximum dimension 1 of grid: 65535
Maximum dimension 2 of grid: 65535
Clock rate: 901500
Total constant memory: 65536
Texture alignment: 512
Concurrent copy and execution: Yes
Number of multiprocessors: 5
Kernel execution timeout: Yes
cela a probablement à voir avec l'utilisation de 100% de chaque noyau. Les flux sont destinés à chevaucher l'exécution du noyau avec des opérations de données. Si chaque appel du noyau utilise complètement votre processeur, alors les noyaux ne se chevaucheront pas. –
Vos noyaux lancent 512 blocs de 512 threads chacun. Le premier lancement du noyau "remplit" la machine, et le second attend le premier. Afin d'assister à l'exécution simultanée de deux noyaux, cela signifie que ces noyaux auront des limites significatives en termes de ressources machine qu'ils utilisent. Si un noyau utilise toutes les ressources de la machine, le second noyau attendra. Ceci est conceptuellement similaire à l'idée que tous les blocs d'une grande grille ne s'exécuteront pas simultanément. Vous ne verrez que le nombre de blocs pouvant être pris en charge par les SM sur votre GPU spécifique. –
@GregK. Si vous voulez fournir une réponse, je voudrais upvote. –