2013-08-12 2 views
0

Я работаю над проектом, который включает в себя много математики. Для одной целевой задачи (например, вычисления градиента) у нас всегда есть две версии реализаций: одна версия ЦП и одна версия CUDA.Как определить функцию использования, которая может быть вызвана как ядром CUDA, так и регулярной функцией C++

Теперь версия процессора написана на обычном C++, а версия ядра написана в CUDA. Если я хочу определить небольшую функцию, например, vec_weight, которая возвращает вес вектора, я должен написать один для процессора, скомпилированного g ++ для версии процессора и одной версии cuda, которая имеет «__ device__» перед он скомпилирован nvcc.

Я не пытаюсь определить « __ host__ __ device__» функцию здесь. То, что я хочу, - это некоторая библиотека, которая может быть вызвана регулярной C++-функцией и ядром CUDA. Я попытался использовать макрос «__CUDACC__», но он не работал.

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

Написание версии процессора в .cu вместо .cpp может решить нашу проблему, но это не то, что мы хотим.

Итак, что мне делать?

Вот фрагмент кода:

head.h:

1 #ifndef HEAD_H 
    2 #define HEAD_H 
    3 #ifdef __cplusplus 
    4 extern "C"{ 
    5 #endif 
    6 __device__ __host__ void myprint(); 
    7 #ifdef __cplusplus 
    8 } 
    9 #endif 
    10 #endif 

head.cu:

1 #include "head.h" 
    2 #include <stdio.h> 
    3 void myprint(){ 
    4 // do something here 
    5 } 

main.cpp

1 #include "head.h" 
2 int main(){ 
3 myprint(); 
4 } 

Я составил глава .cu by:

nvcc -c head.cu 

Ссылка их вместе:

g++ main.cpp head.o -o main (The reason that I didn't use nvcc here is that we are using the PGI's pgcpp in our project and we need it to talk to the PGI's OMP library. But I'm sure that there is something wrong here but I don't know how to fix that.) 

сообщения об ошибках:

In file included from main.cpp:18: 
head.h:6: error: ‘__device__’ does not name a type 
main.cpp: In function ‘int main()’: 
main.cpp:20: error: ‘myprint’ was not declared in this scope 

Так что я уверен, что г ++ не может распознать префикс "__ device__" здесь , Но наш проект требует, чтобы мы использовали PGCPP для компиляции файла cpp, потому что это единственный способ, которым мы можем иметь директивы omp, прекрасно работающие как в Fortran, так и в C (наш проект смешивает C/C++, Fortran и CUDA). Но здесь даже g ++ не может работать, поэтому я думаю, что мы исправим это в первую очередь.

+5

Это именно то, для чего предназначены функции '__host__ __device__'. Почему вы пытаетесь избежать его создания? –

+0

@JaredHoberock Что я пытаюсь сделать, так это создать общий интерфейс, который можно назвать как cuda, так и обычным C++. Мы также не хотим использовать NVCC для компиляции исходного файла на C++. Поскольку обычный C++ не смог распознать «\ __ хост \ __» или «\ __ устройство \ __», как они могут помочь? – zyc

ответ

3

Библиотеки обычно содержат код, скомпилированный для целевого процессора (CPU или GPU), поэтому вам нужно скомпилировать его через NVCC. Следовательно, вы также можете поместить его в файлы .cu.

Если вы можете освободить источники, вы можете поместить код в заголовки и включить их в файлы .cpp или .cu.

Update

Это то, что я сделал в моем коде (hdf функция может быть вызвана с хостом и устройством):

Файл devhost.h

#ifndef FUNCTIONS_H_ 
#define FUNCTIONS_H_ 

int myhost_functin(int); 

#endif 

Файл cu.cu:

__host__ __device__ 
int hdf(int a) { 
    return a + 4; 
} 

int myhost_function(int a) { 
    return hdf(a); 
} 

__global__ 
void kern(int *data) { 
    data[threadIdx.x] = hdf(data[threadIdx.x]); 
} 

cpp.cpp Файл:

#include <stdio.h> 
#include <stdlib.h> 

#include "devhost.h" 

int main() { 
    printf ("%d\n", myhost_function(5)); 
    return 0; 
} 

Это, как я скомпилировать и скомпоновать его:

nvcc -c cu.cu 
gcc -c cpp.cpp 
gcc cpp.o cu.o -lcudart -L/usr/local/cuda-5.5/lib64 

Обратите внимание, что вам нужно связать с CUDART в CU файл имеет вызов устройства.

Update 2

Чуть менее элегантный подход, который до сих пор, кажется, скомпилировать это иметь что-то вроде в вашем файле заголовка:

#ifdef __CUDACC__ 
__host__ __device__ 
#endif 
static int anotherfunction(int a) { 
    return a * 50; 
} 

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

+0

Но я не могу использовать G ++ для связывания библиотеки .cu с моим файлом C++? – zyc

+0

Вы можете использовать компоновщик хоста для связывания файлов объектов с помощью 'nvcc -c' с вашим кодом C, если вы не используете отдельный режим компиляции для кода устройства. – Eugene

+0

Я пробовал, но это не сработало. – zyc

Смежные вопросы