Могу ли я вызвать функциональный макрос в заголовочном файле из функции CUDA __global__?

Это часть моего заголовочного файла aes_locl.h:

.
.
# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) 
# define GETU32(p) SWAP(*((u32 *)(p))) 
# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } 
.
.

Теперь из файла .cu я объявил функцию __ global__ и включил файл заголовка следующим образом:

#include "aes_locl.h"
.....
__global__ void cudaEncryptKern(u32* _Te0, u32* _Te1, u32* _Te2, u32* _Te3, unsigned char* in, u32* rdk, unsigned long* length)
{
    u32 *rk = rdk;
    u32 s0, s1, s2, s3, t0, t1, t2, t3;

    s0 = GETU32(in + threadIdx.x*(i) ) ^ rk[0];
}

Это приводит меня к следующему сообщению об ошибке:

ошибка: вызов функции хоста из функции __ device__/__ global__ разрешен только в режиме эмуляции устройства

У меня есть пример кода, где программист вызывает макрос именно так.

Могу ли я это так назвать, или это вообще невозможно? Если это не так, я буду признателен за некоторые подсказки о том, как лучше всего переписать макросы и присвоить желаемое значение S0.

заранее большое спасибо!!!


person Bartzilla    schedule 28.07.2010    source источник


Ответы (3)


Аппаратное обеспечение не имеет встроенной инструкции поворота, поэтому нет встроенной функции для ее раскрытия (вы не можете раскрыть то, чего не существует!).

Это довольно просто реализовать со сдвигами и масками, например, если x 32-битный, то для поворота влево на восемь бит вы можете сделать:

((x << 8) | (x >> 24))

Где x << 8 будет сдвигать все левые восемь битов (т. е. отбрасывать самые левые восемь битов), x >> 24 будет сдвигать все правые двадцать четыре бита (т. е. отбрасывать все, кроме самых левых восьми битов), а побитовое ИЛИ их вместе дает результат, который вам нужен.

// # define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
# define SWAP(x) (((x << 8) | (x >> 24)) & 0x00ff00ff | ((x >> 8) | (x << 24)) & 0xff00ff00)

Конечно, вы могли бы сделать это более эффективным, признав, что приведенное выше является излишним:

# define SWAP(x) (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8))
person Tom    schedule 03.08.2010

Я думаю, что проблема не в самих макросах - процесс компиляции, используемый nvcc для кода CUDA, запускает препроцессор C обычным образом, поэтому использование файлов заголовков таким образом должно быть в порядке. Я считаю, что проблема в ваших звонках _lrotl и _lrotr.

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

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

person Edric    schedule 29.07.2010
comment
Спасибо, это действительно проблема, если я удалю эти вызовы, теперь все работает нормально, мне просто нужно заменить эти функции действительными функциями cuda, я ценю это !!!! - person Bartzilla; 29.07.2010
comment
Точно так же препроцессор C будет обрабатывать макросы точно так же в коде хоста и устройства. Итак, проблема в том, что после обработки код устройства пытается вызвать функцию хоста. - person Tom; 03.08.2010

Ошибка говорит о том, в чем проблема на самом деле. Вы вызываете функцию/макрос, определенную в другом файле (который принадлежит коду ЦП), изнутри функции CUDA. Это невозможно!

Вы не можете вызывать функции/макросы/код ЦП из функции графического процессора.

Вы должны поместить свои определения (существует ли _lrotl() в CUDA?) внутри того же файла, который будет скомпилирован nvcc.

person karlphillip    schedule 28.07.2010
comment
С макросами все в порядке, поскольку препроцессор просто расширяет их, как и следовало ожидать. Проблема в этом случае, как ответил Эдрик, заключается в том, что макрос содержит вызовы функций, а эти функции предназначены только для хоста. - person Tom; 03.08.2010