Я довольно новичок в CUDA и просто смущен о том, как это работает.Как работают параллельные вычисления CUDA?
Я создал простую пустоту для выполнения на графическом процессоре.
__global__ void Test (int *ch) {
long i = blockIdx.x;
ch[2] = i;
long u = threadIdx.x;
ch[3] = u;
if (i < 640)
{
ch[0]++;
if (u < 480)
{
ch[1]++;
}
}
}
Я назвал пустоту < < < 640480 >>>. Во всех учебниках я видел, что If заменяет «CPU» for-loop. Оригинальный "CPU-Пустота" выглядел следующим образом:
void Test (int *ch) {
h_ch[2] = 640;
h_ch[3] = 480;
for(int a = 0;a < 640;a++)
{
ch[0]++;
for(int b = 0;b < 480;b++)
{
ch[1]++;
}
}
}
Если я печатаю массив сп порожденную CPU я вижу что-то вроде этого: Ch [0] = 640 ч [1] = 307200 ч [2 ] = 640 ch [3] = 480, но что делает GPU?
Я получил следующие результаты: ch [0] = 1038 (значение менялось при каждом запуске!) Ch [1] = 1038 (похоже, ch [0]) ch [2] = 639 ch [3 ] = 31
Что происходит? Я предполагал получить те же результаты, что и на CPU.
Спасибо за ответы
Ниже приведен полный код: (Я просто хочу те же результаты) Вы можете выбрать CPU или GPU
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <iostream>
int *h_ch , *ch;
__global__ void Test (int *ch)
{
long i = blockIdx.x;
ch[2] = i;
long u = threadIdx.x;
ch[3] = u;
if (i < 640)
{
ch[0]++;
if (u < 480)
{
ch[1]++;
}
}
}
void test (int *h_ch)
{
h_ch[2] = 640;
h_ch[3] = 480;
for(int a = 0;a < 640;a++)
{
h_ch[0]++;
for(int b = 0;b < 480;b++)
{
h_ch[1]++;
}
}
}
int main()
{
h_ch = (int *)malloc(4*sizeof(int));
cudaMalloc((void **)&ch,4*sizeof(int));
h_ch[0] = 0;
h_ch[1] = 0;
h_ch[2] = 0;
h_ch[3] = 0;
cudaMemcpy(ch,h_ch,4*sizeof(int),cudaMemcpyHostToDevice);
//Test<<<640,480>>>(ch);
test(h_ch);
//cudaMemcpy(h_ch,ch,4*sizeof(int),cudaMemcpyDeviceToHost);
for(int i = 0;i < 4;i++) printf("%d ",h_ch[i]);
int a;
std::cin >> a;
return 0;
}
Просьба представить полный пример которые будут компилировать и включать информацию о вашем желаемом результате. –
У вас есть несколько потоков, наступающих друг на друга, когда они пытаются обновить два местоположения 'ch [0]' и 'ch [1]'. В GPU несколько потоков выполняются параллельно. Когда все эти потоки пытаются обновить одно и то же место одновременно, возникает хаос. Если вы хотите, чтобы этот код работал правильно, замените обычные обновления (например, 'ch [1] ++;') на атомные обновления (например, 'atomicAdd (ch + 1, 1);' –