Вызов CUDA Hello World из Haskell с использованием FFI дает неверные результаты

Это стандартный файл Hello World CUDA:

#include <stdio.h>
#include "hello.h"

const int N = 7;
const int blocksize = 7;

__global__ void hello_kernel(char *a, int *b) {
    a[threadIdx.x] += b[threadIdx.x];
}

#define cudaCheckError() { \
    cudaError_t e=cudaGetLastError(); \
    if(e!=cudaSuccess) { \
        printf("Cuda failure %s:%d: '%s'\n",__FILE__,__LINE__,cudaGetErrorString(e)); \
        exit(0); \
    } \
}

void hello() {
    char a[N] = "Hello ";
    int b[N] = {15, 10, 6, 0, -11, 1, 0};

    char *ad;
    int *bd;
    const int csize = N*sizeof(char);
    const int isize = N*sizeof(int);

    printf("%s", a);

    cudaMalloc( (void**)&ad, csize );
    cudaMemcpy( ad, a, csize, cudaMemcpyHostToDevice );
    cudaCheckError();

    cudaMalloc( (void**)&bd, isize );
    cudaMemcpy( bd, b, isize, cudaMemcpyHostToDevice );
    cudaCheckError();

    dim3 dimBlock( blocksize, 1 );
    dim3 dimGrid( 1, 1 );
    hello_kernel<<<dimGrid, dimBlock>>>(ad, bd);
    cudaMemcpy( a, ad, csize, cudaMemcpyDeviceToHost );
    cudaCheckError();

    cudaFree( ad );
    cudaCheckError();

    printf("%s\n", a);
}

И его заголовок:

-- hello.h
extern "C" 
void hello();

Это файл Haskell, который вызывает такую ​​функцию:

-- test.hs
{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign.C
import Foreign.Ptr (Ptr,nullPtr)

foreign import ccall "hello" hello :: IO ()

main = hello

Я компилирую его с помощью:

nvcc hello.c -c -o hello.o
ghc test.hs -o test hello.o -L/usr/local/cuda/lib -optl-lcudart

Запуск этой программы с ./test приводит к:

Hello Cuda failure hello.cu:32: 'no CUDA-capable device is detected'

Запуск той же программы с C main(), который просто вызывает hello, производит Hello World, как и ожидалось.

Как заставить Haskell правильно определить устройство?


person MaiaVictor    schedule 25.05.2015    source источник
comment
Почему в вашем коде нет проверки ошибок CUDA API? Неправильный ответ обычно означает, что вы никогда не бегали. Но без какой-либо проверки ошибок, как вы могли знать?   -  person talonmies    schedule 25.05.2015
comment
Я только что взял Hello World из Интернета. Я мог бы добавить некоторые проверки ошибок и обновить вопрос.   -  person MaiaVictor    schedule 25.05.2015
comment
Вы должны быть в состоянии написать собственный C++ main, который вызывает функцию hello и проверяет ее работу. Возможно, ваша установка CUDA не работает, или это может быть проблема haskell-CUDA, но на данный момент очень сложно сказать   -  person talonmies    schedule 25.05.2015
comment
Я так делал, это работает. Во всяком случае, обновил вопрос.   -  person MaiaVictor    schedule 25.05.2015
comment
Итак, у вас есть ответ. API среды выполнения не может обнаружить допустимое устройство при вызове из того, что вы используете в Haskell.   -  person talonmies    schedule 25.05.2015
comment
Хорошо. Я обновил актуальный вопрос.   -  person MaiaVictor    schedule 25.05.2015


Ответы (2)


Возможно, это не связано, но мне удалось воспроизвести вашу ошибку на Mac с отдельными встроенными и дискретными видеокартами. Когда в Системных настройках включено «Автоматическое переключение графики» (и приложения для 3D-графики не запущены), я получаю ту же ошибку «Устройство с поддержкой CUDA не обнаружено».

Когда я отключаю автоматическое переключение графики, он заставляет Mac использовать дискретную видеокарту, а затем программа работает как положено.

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

person Jeff Ames    schedule 26.05.2015

Используя ghc 7.8.3 и nvcc V6.5.12, я обнаружил, что ваш код работает так, как ожидалось. Единственная другая вещь, которую я сделал, это назвал hello.c как hello.cu.

/:cuda_haskell> nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2014 NVIDIA Corporation
Built on Thu_Jul_17_19:13:24_CDT_2014
Cuda compilation tools, release 6.5, V6.5.12
/:cuda_haskell> nvcc -o hello.o -c hello.cu
/:cuda_haskell> ghc main.hs -o hello_hs hello.o -L/usr/local/cuda/lib -optl-lcudart
Linking hello_hs ...
/:cuda_haskell> ./hello_hs
Hello World!
/:cuda_haskell> cat main.hs
-- main.hs
{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign.C
import Foreign.Ptr (Ptr,nullPtr)

foreign import ccall "hello" hello :: IO ()

main = hello
person nilweed    schedule 26.05.2015
comment
Ой. Это странно. Может быть, это что-то конкретное для моей машины, тогда. Извините, если это так, и спасибо! - person MaiaVictor; 26.05.2015