Zrobiłem mały moduł C, aby poprawić wydajność, ale GHC nie inline funkcji inline, a koszty połączeń eliminuje przyspieszenie. Przykładowo test.h
:Jak wymusić GHC na wywoływanych wywołaniach FFI?
int inc (int x);
test.c
:
#include "test.h"
int inc(int x) {return x + 1;}
Test.hc
:
{-# LANGUAGE ForeignFunctionInterface #-}
module Test (inc) where
import Foreign
import Foreign.C
foreign import ccall unsafe "test.h inc" c_inc :: CInt -> CInt
inc = fromIntegral . c_inc . fromIntegral
{-# INLINE c_inC#-}
{-# INLINE inC#-}
Main.hs
:
import System.Environment
import Test
main = do {args <- getArgs; putStrLn . show . inc . read . head $ args }
Making:
$ gcc -O2 -c test.c
$ ghc -O3 test.o Test.hs
$ ghc --make -O3 test.o Main
$ objdump -d Main > Main.as
Wreszcie w Main.as
mam callq <inc>
instrukcji zamiast pożądanych inc
wieku.
Oczekujesz, że ghc wstawi funkcję C w wygenerowanym kodzie? Może to zadziałać, jeśli użyjesz opcji -via-C, w przeciwnym razie jest to beznadziejne (ponieważ wymagałoby ghc do odczytania kodu C i wygenerowania dla niego kodu). – augustss
Nie możliwe przy braku optymalizacji czasu łącza. Jednym (hackowskim) podejściem jest próba skompilowania kodu Haskell i C do LLVM, połączenie plików .bc z 'llvm-link', optymalizacja za pomocą' opt', a następnie wyemitowanie kodu wykonywalnego z 'llc'. –
@MikhailGlushenkov, czy mógłbyś napisać szkic wykonywania sekwencji poleceń? Nie udało mi się znaleźć w Google sposobu uzyskania plików '.bc' z kodu haskell. – leventov