У меня есть линейный int
массив arr
, который находится на глобальной памяти CUDA. Я хочу установить подмассивы arr
до определенных значений. Начальные индексы подмассива задаются starts
массив, в то время как длина каждого подмассива указана в counts
массив.
Что я хочу сделать, это установить значение подмассива i
начиная с starts[i]
и продолжая до counts[i]
к стоимости starts[i]
, То есть операция это:
arr[starts[i]: starts[i]+counts[i]] = starts[i]
Я думал об использовании memset()
в ядре для установки значений. Тем не менее, он не записывается правильно (элементам массива присваиваются некоторые случайные значения). Код, который я использую:
#include <stdlib.h>
__global__ void kern(int* starts,int* counts, int* arr,int* numels)
{
unsigned int idx = threadIdx.x + blockIdx.x*blockDim.x;
if (idx>=numels[0])
return;
const int val = starts[idx];
memset(&arr[val], val, sizeof(arr[0])*counts[idx]) ;
__syncthreads();
}
Обратите внимание, что numels[0]
содержит количество элементов в starts
массив.
Я проверил код с cuda-memcheck()
но не получил никаких ошибок. я использую PyCUDA
, если это актуально. Я, вероятно, неправильно понимаю использование memset здесь, поскольку я изучаю CUDA.
Можете ли вы предложить способ исправить это? Или другой эффективное способ сделать эту операцию.
П.С .: Я знаю это thrust::fill()
Возможно, я смогу сделать это хорошо, но так как я изучаю CUDA, я хотел бы знать, как это сделать без использования внешних библиотек.
Реализации memset и memcpy в коде устройства CUDA генерируют простые последовательные операции с байтовыми значениями (и обратите внимание, что memset не может устанавливать ничего, кроме байтовых значений, что может способствовать возникновению проблемы, которую вы видите, если значения, которые вы пытаетесь установить, являются больше 8 бит).
Вы можете заменить вызов memset чем-то вроде этого:
const int val = starts[idx];
//memset(&arr[val], val, sizeof(arr[0])*counts[idx]) ;
for(int i = 0; i < counts[idx]; i++)
arr[val + i] = val;
Производительность этого кода, вероятно, будет лучше, чем у встроенного memset.
Обратите внимание также, что __syncthreads()
Вызов в конце вашего ядра является ненужным и потенциальным источником тупика и должен быть удален. Увидеть Вот для дополнительной информации.
Других решений пока нет …