Моя глобальная функция, написанная на Cuda, запускает только последний блок - PullRequest
0 голосов
/ 09 ноября 2018

Решено: Извините, это моя ошибка, я должен использовать atomicAdd(times,1); вместо *times++ в функции ядра.

Я вызываю функцию ядра следующим образом

dim3 Dg(blockSize, blockSize, blockSize);
dim3 Db(8, 8, 8);
voxelize << < Dg, Db >> > ();
cudaDeviceSynchronize();

Но я обнаружил, что моя программа решает только часть проблемы, поэтому я использую printf() в своей глобальной функции voxelize (), как в следующем коде

__global__ void voxelize(){
    printf("the thread blockIdx.x %d, blockIdx.y %d blockIdx.z %d\n", blockIdx.x, blockIdx.y, blockIdx.z);
    unsigned int xIndex = blockDim.x * blockIdx.x + threadIdx.x;
    unsigned int yIndex = blockDim.y * blockIdx.y + threadIdx.y;
    unsigned int zIndex = blockDim.z * blockIdx.z + threadIdx.z;
    unsigned int i = zIndex * blockDim.x*blockDim.y+ yIndex * blockDim.x+ xIndex;
}    

Выходные данные показали только последнюю часть каждого выполненного измерения (то есть blockIdx.x всегда равен 5, только некоторые из blockIndex.z изменяются с 0 на 5). Но я не понимаю, почему что-то не так, когда я вызываю эту функцию ядра? Мой компьютер с GTX1050Ti MaxQ и cuda 10.


После этого я передал указатель ядру для контроля времени работы.

 int blockSize = ceil(pow(triangles.size() 69664 / 512.0, 1.0 / 3));
 dim3 Dg(blockSize, blockSize, blockSize);
 dim3 Db(8, 8, 8);
 int* times = new int(0);
 int* gpu_times;
 cudaMalloc((void **)&gpu_times, sizeof(int));
 cudaMemcpy(gpu_times, times, sizeof(int), cudaMemcpyHostToDevice);
 voxelize << < Dg, Db >> > (gpu_times);
 cudaDeviceSynchronize();
 cudaMemcpy(times, gpu_times, sizeof(int), cudaMemcpyDeviceToHost);
 std::cout << *times << std::endl;

ядро ​​модифицировано как

__global__ void voxelize(int* times){
    (*times)++;
    printf("the thread blockIdx.x %d, blockIdx.y %d blockIdx.z %d\n", blockIdx.x, blockIdx.y, blockIdx.z);
    unsigned int xIndex = blockDim.x * blockIdx.x + threadIdx.x;
    unsigned int yIndex = blockDim.y * blockIdx.y + threadIdx.y;
    unsigned int zIndex = blockDim.z * blockIdx.z + threadIdx.z;
    unsigned int i = zIndex * blockDim.x*blockDim.y+ yIndex * blockDim.x+ xIndex;
}    

вывод enter image description here вывод показывает, что он работает 141 раз, но на самом деле вывод должен быть намного больше, чем 69664


извините, это моя вина, я должен использовать atomicAdd(times,1); вместо *times++.

Но почему printf() выводит только часть индекса, как я описал ранее?

1 Ответ

0 голосов
/ 09 ноября 2018

Для вашей проблемы с printf

Вам нужно позвонить cudaDeviceSynchronize() (проверка ошибок для ясности опущена), а также вам нужно cudaDeviceSetLimit(...), если вы используете много printf (что имеет место):

#include <stdio.h>

__global__ void voxelize(){
    printf("the thread blockIdx.x %d, blockIdx.y %d blockIdx.z %d\n", blockIdx.x, blockIdx.y, blockIdx.z);
    unsigned int xIndex = blockDim.x * blockIdx.x + threadIdx.x;
    unsigned int yIndex = blockDim.y * blockIdx.y + threadIdx.y;
    unsigned int zIndex = blockDim.z * blockIdx.z + threadIdx.z;
    unsigned int i = zIndex * blockDim.x*blockDim.y+ yIndex * blockDim.x+ xIndex;
}

int main()
{
  // Increase device printf buffer to 50 MiB
  cudaDeviceSetLimit(cudaLimitPrintfFifoSize, 50*1024*1024);
  dim3 Dg(5, 5, 5);
  dim3 Db(8, 8, 8);
  voxelize<<<Dg, Db>>>();
  cudaDeviceSynchronize();

  return 0;
}

Это напечатает что-то вроде:

the thread blockIdx.x 2, blockIdx.y 3 blockIdx.z 4
the thread blockIdx.x 2, blockIdx.y 3 blockIdx.z 4
the thread blockIdx.x 2, blockIdx.y 3 blockIdx.z 4
the thread blockIdx.x 2, blockIdx.y 3 blockIdx.z 4
the thread blockIdx.x 2, blockIdx.y 3 blockIdx.z 4
[...]

Затем вы можете проверить это так:

# This will keep one line per block and count them, so 5*5*5 == 125
$ ./a.out | sort | uniq | wc -l
125

# This will output one line per thread and count them, so 5*5*5 * 8*8*8 == 64000
$ ./a.out | wc -l
64000

Для вас считается проблема

Вы не можете этого сделать: (*times)++;. У вас будут проблемы с параллелизмом. Вам нужно использовать атомарные функции .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...