optimization - Haskell 的有限差异,或如何禁用潜在的优化

标签 optimization haskell numerical-methods rounding-error

我想实现以下简单(一阶)有限差分函数:

finite_difference :: Fractional a => a -> (a -> a) -> a -> a
finite_difference h f x = ((f $ x + h) - (f x)) / h

您可能知道,有一个微妙的问题:必须确保 (x + h)x 相差一个可精确表示的数字。否则,由于 (f $ x + h) - (f x) 涉及灾难性取消这一事实,结果会产生巨大的错误(并且必须仔细选择 h ,但这不是我的问题)。

在 C 或 C++ 中,问题可以这样解决:

volatile double temp = x + h;
h = temp - x;

并且 volatile 修饰符禁用与变量 temp 相关的任何优化,因此我们确信“聪明”的编译器不会优化掉这两行。

我对 Haskell 的了解还不够多,还不知道如何解决这个问题。恐怕

let temp = x + h
    hh = temp - x 
in ((f $ x + hh) - (f x)) / h

将被 Haskell(或它使用的后端)优化掉。我如何在此处获得等效的 volatile (如果可能的话,不牺牲懒惰)?我不介意 GHC 的具体答案。

最佳答案

我有两个解决方案和一个建议:

第一个解决方案:您可以保证不会使用两个辅助函数和 NOINLINE pragma 进行优化:

norm1 x h = x+h
{-# NOINLINE norm1 #-}

norm2 x tmp = tmp-x
{-# NOINLINE norm2 #-}

normh x h = norm2 x (norm1 x h)

这会奏效,但会产生少量成本。

第二种解决方案:使用 volatile 用 C 语言编写归一化函数,并通过 FFI 调用它。性能损失将是最小的。

现在建议:目前数学尚未优化,因此目前可以正常工作。您担心它会在未来的编译器中中断。我认为这不太可能,但也不是不太可能,我也不想防范它。因此,编写一些涵盖相关案例的单元测试。然后,如果它在未来确实发生故障(出于任何原因),您将确切知道原因。

关于optimization - Haskell 的有限差异,或如何禁用潜在的优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5639603/

相关文章:

python - 使用 scipy.optimize.minimize 最小化 Python 中的约束函数时出现问题

haskell - 为什么这个等效程序无法编译?

haskell - 如何处理多参数类型类的功能,谁不需要类型类的每种类型?

Haskell,实现幺半群。什么是 Semigroup,为什么它表现得如此奇怪?

python - 使用 python(或其他有用的语言)在积分内拟合参数

c - 3D vector ,返回指针还是返回结构?

mysql - 对许多参数表使用数据库投票表

performance - 最新至强上的 FP 密集型超线程性能

c++ - 实现最速下降算法,可变步长

c - 应为 ‘double *’,但参数的类型为 ‘double **’