从 Haskell 编译到 WASM 时,简单的递归和是二次的

问题描述 投票:0回答:1

以下 Haskell 函数:

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where

import Data.Word (Word32)

sum' :: Word32 -> Word32
sum' 0 = 0
sum' n = n + sum' (n-1)

foreign export javascript "sum" sum' :: Word32 -> Word32

main :: IO ()
main = print (sum' 10000000)

编译为 WASM 时,在

n
上呈二次方,而不是如预期的线性。因此,它比原生版本慢数百万倍,这对于 WASM 来说是不期望的。这是编译器错误,还是我做错了什么?

我正在使用 GHC 9.11.20240817,使用以下命令:

wasm32-wasi-ghc main.hs -O2 -no-hs-main -optl-mexec-model=reactor

接下来是后链接步骤:

$(wasm32-wasi-ghc --print-libdir)/post-link.mjs -i main.wasm -o main.js

然后我从 JS 导入

sum
并在不同的 n 上调用它。

haskell webassembly ghc
1个回答
0
投票

您是否有可能将二次性能误认为是“无性能”? 在我对版本 9.11.20240818 的测试中,我看到线性性能高达

sum' 258690872
,然后当编译为命令模块并在
sum' 258690873
下运行时,从
wasmtime
开始不会终止。 具体来说,如果我编译:

module Main where

import Data.Word (Word32)

sum' :: Word32 -> Word32
sum' 0 = 0
sum' n = n + sum' (n-1)

main :: IO ()
main = print $ sum' 258690872

wasm32-wasi-ghc -O2 Sum.hs
并使用
wasmtime
运行时运行它,运行时间约为 7 秒。 如果我将
258690872
增加到
258690873
,它不会终止。

它看起来与错误的堆栈溢出处理有关,因为使用 RTS

-K
选项,我可以让
sum' 258690872
以堆栈溢出错误终止,无限期挂起,或在大约 7 秒内完成,因为堆栈大小增加了。

我已提交问题#25213

© www.soinside.com 2019 - 2024. All rights reserved.