Манипулирование указателем устройства CUDA - PullRequest
3 голосов
/ 06 мая 2011

Я использовал:

float *devptr;
//...
cudaMalloc(&devptr, sizeofarray);
cudaMemcpy(devptr, hostptr, sizeofarray, cudaMemcpyHostToDevice);

в CUDA C для выделения и заполнения массива. Теперь я пытаюсь запустить ядро ​​cuda, например ::1004

__global__ void kernelname(float *ptr)
{
   //...
}

в этом массиве, но со значением смещения. В C / C ++ это было бы примерно так:

kernelname<<<dimGrid, dimBlock>>>(devptr+offset);

Однако, похоже, это не работает.

Есть ли способ сделать это без отправки значения смещения ядру в отдельном аргументе и использования этого смещения в коде ядра? Есть идеи как это сделать?

Ответы [ 2 ]

9 голосов
/ 06 мая 2011

Арифметика с указателями прекрасно работает в CUDA.Вы можете добавить смещение к указателю CUDA в коде хоста, и оно будет работать правильно (запоминание смещения не смещение в байтах, это простое смещение слова или элемента).

РЕДАКТИРОВАТЬ: простой рабочий пример:

#include <cstdio>
int main(void)
{

    const int na = 5, nb = 4;
    float a[na] = { 1.2, 3.4, 5.6, 7.8, 9.0 };
    float *_a, b[nb];

    size_t sza = size_t(na) * sizeof(float);
    size_t szb = size_t(nb) * sizeof(float);

    cudaFree(0);

    cudaMalloc((void **)&_a, sza );
    cudaMemcpy( _a, a, sza, cudaMemcpyHostToDevice);
    cudaMemcpy( b, _a+1, szb, cudaMemcpyDeviceToHost);

    for(int i=0; i<nb; i++)
        printf("%d %f\n", i, b[i]);

    cudaThreadExit();
}

Здесь вы можете видеть, что смещение слова / элемента было применено к указателю устройства во втором вызове cudaMemcpy, чтобы начать копирование со второго слова, а не с первого.

1 голос
/ 19 сентября 2016

Арифметика указателей работает с кодом на стороне хоста, она довольно часто используется в примере кода, предоставленном nvidia.

"Линейная память существует на устройстве в 40-битном адресном пространстве, поэтому отдельно выделенные объекты могут ссылаться друг на друга с помощью указателей, например, в двоичном дереве."

Подробнее на: http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#ixzz4KialMz00

И из документации по примитивам производительности (npp), прекрасный пример арифметики указателей.

"4.5.1. Выбор канала - указатель источника изображения Это указатель на интересующий канал в первом пикселе исходного изображения. Например. если pSrc является указатель на первый пиксель в области интереса трехканального изображения. Используя соответствующую копию выбранного канала примитивно можно скопировать второй канал этого исходного изображения в первый канал пункта назначения изображение, заданное pDst путем смещения указателя на единицу: nppiCopy_8u_C3CR (pSrc + 1, nSrcStep, pDst, nDstStep, oSizeROI); "

* Примечание: это работает без умножения на количество байтов на элемент данных, поскольку компилятор знает тип данных указателя и соответственно вычисляет адрес.

В C и C ++ арифметику указателей можно выполнить, как указано выше, или с помощью записи & ptr [offset] (для возврата адреса памяти устройства из данных вместо значения значение не будет работать в памяти устройства из кода на стороне хоста). При использовании любого обозначения размер типа данных обрабатывается автоматически, а смещение указывается в виде числа элементов данных, а не байтов.

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