Cuda/cudafy 3d индексация

Пытаясь разобраться в cuda, после того, как я не понял подобные вопросы, связанные с stackru, я решил протестировать пример (я использую cudafy.net для C#, но базовая cuda должна быть доступной)

Я хочу сделать следующее. Отправьте ядро ​​4x4x4 матрицу и получите 4x4x4 в соответствии с этой логикой:

if(input[x,y,z] == 1)
    output[x+1, y, z]++;

if(input[x,y,z] == 2)
    output[x-1, y, z]++;

Я изучил следующий пример cudafy.

public const int N = 1 * 1024;

//Omissions

gpu.Launch(128, 1, function, dev_a, dev_b, dev_c);

ядро:

[Cudafy]
public static void add_0(GThread thread, int[] a, int[] b, int[] c)
{
    int tid = thread.blockIdx.x; // (tid 0 -> 127, from my understanding)
    while (tid < N)
    { 
        c[tid] = a[tid] + b[tid];
        tid += thread.gridDim.x;
    }
}

А потом попытался перенести его в 3d. Я не могу получить правильную индексацию. Скажи, что у меня есть следующее. (три массива здесь только для проверки индексации)

int size = 4;
int[] dev_delta = gpu.Allocate<int>(size * size * size);
int[] dev_space = gpu.Allocate<int>(size * size * size);
int[] dev_result = gpu.Allocate<int>(size * size * size);

gpu.Launch(new dim3(4, 4, 4), 1, "testIndex", dev_delta, dev_space, dev_result);

И ядро:

[Cudafy]
public static void testIndex(GThread thread, int[] delta, int[] space, int[] result)
{
    int x = thread.blockIdx.x;
    int y = thread.blockIdx.y;
    int z = thread.blockIdx.z;
    delta[x]++;
    space[y]++;
    result[z]++;
}

Наивно я бы ожидал следующего:

delta = {4,4,4,4,0,0,0,0,0, ... 0,0}
space = {4,4,4,4,0,0,0,0,0, ... 0,0}
result = {4,4,4,4,0,0,0,0,0 ... 0,0}

Но я получаю:

delta = {1,1,1,1,0,0,0,0,0, ... 0,0}
space = {1,1,1,1,0,0,0,0,0, ... 0,0}
result = {1,0,0,0,0,0,0,0,0 ... 0,0}

Это не имеет смысла для меня, ясно, что я что-то упустил.

Вопросы:

Сколько тем я запускаю?

Как вы относитесь к "индексации" моего примера задачи в 3 измерениях (начиная с потоков 4x4x4 и получая переменные для flat3DArray[x * sizeY * sizeZ + y * sizeZ + z])?

Как вы относитесь к "индексации" моего примера задачи в двух измерениях? (Начиная с потоков 4х4, а затем пусть каждый поток обрабатывает столбец глубины длины 4)

Я обнаружил, что это может быть актуально. Почему в ядре CUDA z всегда равен нулю, если это то, что меня портит, я все равно был бы признателен за чистые ответы, чтобы разобраться в моем мозгу.

1 ответ

Решение

Сколько тем я запускаю? Вы запускаете 1 поток на блок, следовательно, всего 16, поскольку параметр Z не используется. Для лучшей производительности я бы рекомендовал также использовать потоки (не менее 128 и не более 32).

Как вы относитесь к "индексации" моего примера задачи в 3 измерениях (начиная с потоков 4x4x4 и получая переменные для flat3DArray[x * sizeY * sizeZ + y * sizeZ + z])? Второй параметр gpu.Launch Метод для потоков. x, y а также z следовательно, может быть threadIdx.x, threadIdx.y а также threadIdx.z соответственно. Но вы также можете использовать много блоков, таким образом, threadIdx.x + blockDim.x * blockIdx.x может быть хорошим пиком.

Ссылка, которую вы предоставили здесь, объясняет, почему ваше измерение Z не имеет значения. CUDAfy.Net предоставляет функцию запуска, которая дополнительно вызывает вызов API CUDA/C времени выполнения cuda. При передаче параметров из точечной сети в собственное окружение кажется, что CUDAfy.Net просто игнорирует аргумент Z, оставляя его одному. (это, скорее всего, связано с тем, что ранние версии CUDA не поддерживали параметр Z, отличный от одного). Это не просто объяснение, потому что CUDA теперь поддерживает значение Z, отличное от единицы, но ваш параметр просто игнорируется в реализации CUDAfy.Net.

Другие вопросы по тегам