Я реализовал алгоритм в R
, в Rcpp
(C++
библиотека, которая позволяет легко генерировать DLL, вызываемые из R
) и в Haskell (доступно здесь ).У меня есть две разные реализации в Haskell: одна использует штучные массивы, а другая - нераспакованные массивы (оба изменяемых массива).
Вот выражение, вычисленное алгоритмом:
Бесполезно объяснять это выражение, это просто для того, чтобы показать, что это серия, усеченная до целого числа m
.
Я сделал DLL из реализации Haskell, которая вызывается из R
(с помощью библиотеки inline-r
).Так что я могу сравнить скорость четырех реализаций в R
.При малых значениях m
победителем становится C++
.Но когда я увеличиваю m
, Хаскелл бьет C++
.Вот пример эталонных тестов для примера с m = 40
:
> benchmarks <- function(m){
+ microbenchmark(
+ R = R(m), # R evaluation
+ Rcpp = Rcpp(m), # Rcpp (C++) evaluation
+ Haskell = Haskell(m), # Haskell evaluation
+ Haskell2 = Haskell2(m), # Haskell evaluation with unboxed arrays
+ times = 2
+ )
+ }
> benchmarks(40L)
Unit: seconds
expr min lq mean median uq max neval cld
R 100.923679 100.923679 100.948899 100.948899 100.974118 100.974118 2 d
Rcpp 27.207624 27.207624 27.252485 27.252485 27.297347 27.297347 2 c
Haskell 6.981935 6.981935 7.147086 7.147086 7.312237 7.312237 2 a
Haskell2 8.447389 8.447389 8.629766 8.629766 8.812144 8.812144 2 b
Один говорит, что распакованные массивы более эффективны, чем штучные массивы.Однако это не тот случай, как вы можете видеть.
В чем причина?Можно ли включить опцию GHC, чтобы извлечь выгоду из эффективности распакованных массивов?Я делаю свои DLL с настройками по умолчанию foreign-library
в файле cabal
:
foreign-library Hypergeom
buildable: True
type: native-shared
if os(Windows)
options: standalone
other-modules: HyperGeomR
build-depends: base >=4.7 && < 5
, hypergeomPFQ
, inline-r
hs-source-dirs: src-dll
c-sources: StartEnd.c
default-language: Haskell2010