Глобальный CUDA (как в C) динамические массивы, выделенные памяти устройства

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException, что имеет смысл.

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
7
задан Voltaire 17 September 2008 в 01:55
поделиться

6 ответов

Что-то вроде этого должно, вероятно, работать.

#include <algorithm>

#define NDEBUG
#define CUT_CHECK_ERROR(errorMessage) do {                                 \
        cudaThreadSynchronize();                                           \
         cudaError_t err = cudaGetLastError();                             \
         if( cudaSuccess != err) {                                         \
                     fprintf(stderr, "Cuda error: %s in file '%s' in line %i : %s.\n",    \
                                             errorMessage, __FILE__, __LINE__, cudaGetErrorString( err) );\
                     exit(EXIT_FAILURE);                                                  \
                 } } while (0)


__device__ float *devPtr;

__global__
void kernel1(float *some_neat_data)
{
    devPtr = some_neat_data;
}

__global__
void kernel2(void)
{
    devPtr[threadIdx.x] *= .3f;
}


int main(int argc, char *argv[])
{
    float* otherDevPtr;
    cudaMalloc((void**)&otherDevPtr, 256 * sizeof(*otherDevPtr));
    cudaMemset(otherDevPtr, 0, 256 * sizeof(*otherDevPtr));

    kernel1<<<1,128>>>(otherDevPtr);
    CUT_CHECK_ERROR("kernel1");

    kernel2<<<1,128>>>();

    CUT_CHECK_ERROR("kernel2");

    return 0;
}

Дайте ему водоворот.

5
ответ дан 7 December 2019 в 07:53
поделиться

Проведите некоторое время, фокусируясь на обильной документации, предлагаемой NVIDIA.

Из руководства по программированию:

float* devPtr;
cudaMalloc((void**)&devPtr, 256 * sizeof(*devPtr));
cudaMemset(devPtr, 0, 256 * sizeof(*devPtr));

Это - простой пример того, как выделить память. Теперь, в Ваших ядрах, необходимо принять указатель на плавание как так:

__global__
void kernel1(float *some_neat_data)
{
    some_neat_data[threadIdx.x]++;
}

__global__
void kernel2(float *potentially_that_same_neat_data)
{
    potentially_that_same_neat_data[threadIdx.x] *= 0.3f;
}

Таким образом, теперь можно вызвать их как так:

float* devPtr;
cudaMalloc((void**)&devPtr, 256 * sizeof(*devPtr));
cudaMemset(devPtr, 0, 256 * sizeof(*devPtr));

kernel1<<<1,128>>>(devPtr);
kernel2<<<1,128>>>(devPtr);

Поскольку эти данные используются в многочисленных функциях, я хотел бы, чтобы они были глобальны.

Существует немного серьезных оснований использовать globals. Это определенно не то. Я оставлю его как осуществление для расширения этого примера для включения перемещения "devPtr" в глобальную область видимости.

Править:

Хорошо, фундаментальная проблема - это: Ваши ядра могут только память устройства доступа и единственные указатели глобальной области видимости, которые они могут использовать, GPU. Когда вызов ядра от Вашего ЦП, негласно что происходит, состоит в том, что указатели и примитивы копируются в регистры GPU и/или общую память, прежде чем ядро будет выполнено.

Таким образом, самое близкое, которое я могу предложить, является этим: используйте cudaMemcpyToSymbol () для достижения целей. Но в фоновом режиме полагайте, что другой подход мог бы быть Правильной Вещью.

#include <algorithm>

__constant__ float devPtr[1024];

__global__
void kernel1(float *some_neat_data)
{
    some_neat_data[threadIdx.x] = devPtr[0] * devPtr[1];
}

__global__
void kernel2(float *potentially_that_same_neat_data)
{
    potentially_that_same_neat_data[threadIdx.x] *= devPtr[2];
}


int main(int argc, char *argv[])
{
    float some_data[256];
    for (int i = 0; i < sizeof(some_data) / sizeof(some_data[0]); i++)
    {
        some_data[i] = i * 2;
    }
    cudaMemcpyToSymbol(devPtr, some_data, std::min(sizeof(some_data), sizeof(devPtr) ));
    float* otherDevPtr;
    cudaMalloc((void**)&otherDevPtr, 256 * sizeof(*otherDevPtr));
    cudaMemset(otherDevPtr, 0, 256 * sizeof(*otherDevPtr));

    kernel1<<<1,128>>>(otherDevPtr);
    kernel2<<<1,128>>>(otherDevPtr);

    return 0;
}

Не забывайте '-host-compilation=c ++' для этого примера.

1
ответ дан 7 December 2019 в 07:53
поделиться

Я шел вперед и попробовал решение выделения временного указателя и передачи его к простой глобальной функции, подобной kernel1.

Хорошие новости - то, что это действительно работает :)

Однако я думаю, что это путает компилятор, поскольку я теперь получаю "Консультацию: не Может сказать то, на что указывает указатель, принимая пространство глобальной памяти" каждый раз, когда я пытаюсь получить доступ к глобальным данным. К счастью предположение, оказывается, корректно, но предупреждения являются раздражающими.

Так или иначе для записи - я посмотрел на многие примеры и действительно пробегал упражнения Nvidia, где точка должна заставить вывод говорить "Корректный!". Однако я не посмотрел на всех них. Если кто-либо знает о sdk примере, где они делают динамическое выделение памяти глобального устройства, я все еще хотел бы знать.

1
ответ дан 7 December 2019 в 07:53
поделиться

Erm, это было точно, что проблема перемещения devPtr к глобальной области видимости, которая была моей проблемой.

У меня есть реализация, которая делает точно, что, с этими двумя ядрами, имеющими указатель на данные, передал в. Я явно не хочу передавать в тех указателях.

Я прочитал документацию справедливо тесно и подбросил форумы Nvidia ударом (и Google, искавший в течение приблизительно одного часа), но я не нашел реализацию глобального динамического массива устройства, который на самом деле работает (я попробовал несколько что компиляция и затем перестал работать новыми и интересными способами).

0
ответ дан 7 December 2019 в 07:53
поделиться

проверьте образцы, включенные с SDK. Многие из тех демонстрационных проектов являются достойным способом учиться примером.

0
ответ дан 7 December 2019 в 07:53
поделиться

Поскольку эти данные используются во многих функциях, я хотел бы, чтобы они были глобальными.

-

Есть несколько веских причин использовать глобальные переменные. Это точно не тот. Я оставлю это как упражнение, чтобы расширить этот пример, включив перемещение «devPtr» в глобальную область.

Что, если ядро ​​оперирует большой константной структурой, состоящей из массивов? Использование так называемой постоянной памяти не вариант, потому что она очень ограничена по размеру ... так что вы должны поместить ее в глобальную память?

0
ответ дан 7 December 2019 в 07:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: