Использование GHC с NVCC
В качестве альтернативы ускорению я пытаюсь вызвать код CUDA вместо FFI на Haskell.
Вот простая программа, которая не компилируется:
cuda_code.cu:
void cuda_init() {
cudaFree (0);
cudaThreadSynchronize ();
}
Test.hs:
foreign import ccall unsafe "cuda_init" cuda_init :: IO ()
main = cuda_init
Я собрал с
$> nvcc -c -o cuda_code.o cuda_code.cu
$> ghc Test cuda_code.o
и получил несколько ошибок компоновки (неопределенная ссылка на cudaFree и т. д.). Это не очень удивительно, и очевидное решение (для меня) состоит в том, чтобы связаться с NVCC, используя -pgml nvcc
, (Это работало, когда я использовал Intel CILK+ в своем коде C: я просто изменил компоновщик на ICC, и все работало просто отлично.)
Однако использование NVCC для связи приводит к ошибке компоновки:
ghc Test -pgml nvcc cuda_code.o
[1 of 1] Compiling Main ( Test.hs, Test.o )
Linking Test ...
nvcc fatal : Unknown option 'u'
Бег
strace -v -f -e execve ghc Test -pgml nvcc cuda_code.o
(есть ли более простой способ?) Я обнаружил ghc
звонит nvcc
с
nvcc ... -L~/ghc... -L... -l... -l... -u ghczmprim_GHC... -u ghc...
Я предполагаю -u
варианты предназначены для связыванияgcc
(и, видимо, icc
) с неопределенными символами, что-то nvcc
явно не нравится
Я не знаю, как GHC связывает файлы. Мысли о том, как я могу получить GHC для ссылки на мой код CUDA?
--------РЕДАКТИРОВАТЬ-----------------
Кто-то предложил мне попробовать установить связь с GCC (как обычно), но передать необходимые параметры компоновщика, чтобы gcc
так что он может ссылаться на библиотеки CUDA. Если кто-нибудь знает, что это может быть, это, вероятно, сработает!
2 ответа
Я понял, как заставить это работать.
cudaTest.cu:
// the `extern "C"` is important! It tells nvcc to not
// mangle the name, since nvcc assumes C++ code by default
extern "C"
void cudafunc() {
cudaFree(0);
cudaThreadSynchronize();
}
Test.hs
foreign import ccall unsafe "cudafunc" cudaFunc :: IO ()
main = cudaFunc
Компилировать с:
>nvcc -c -o cudaTest.o cudaTest.cu
>ghc --make Test.hs -o Test cudaTest.o -optl-lcudart
Я также попытался дать GHC возможность -pgmc g++
и удаление extern "C"
(что я ожидал работать), но получил ошибки компиляции в некоторых заголовочных файлах CUDA. Вероятно, есть какой-то простой способ исправить это, так что вам не нужно явно отмечать каждую функцию extern "C"
,
GHC использует /usr/lib/ghc/settings
определить параметры компилятора и компоновщика, а также файлы для каждого пакета, такие как /var/lib/ghc/package.conf.d/builtin_rts.conf
определить специфичные для пакета опции компоновщика. (Выборочная директория будет иметь их в ${GHC}/lib/ghc-${VERSION}/settings
а также ${GHC}/lib/ghc-${VERSION}/package.conf.d
соответственно.)
Вот что я нашел для РТС:
ld-options: -u ghczmprim_GHCziTypes_Izh_static_info -u
ghczmprim_GHCziTypes_Czh_static_info -u
ghczmprim_GHCziTypes_Fzh_static_info -u
ghczmprim_GHCziTypes_Dzh_static_info
...
Согласно ld
справочная страница, -u
опция определяет символ как неопределенный extern
это должно быть определено где-то еще.
Насколько я знаю, это единственный пакет, который имеет эти обычаи -u
варианты в ld-options:
раздел package.conf.d
,
К сожалению, они должны быть переведены для компилятора / компоновщика, который использует другой интерфейс опции.
Будьте так добры и держите людей в курсе об этом на haskell-cafe@haskell.org. Я уверен, что другие тоже пытаются что-то подобное!