理想情况下,一个由简洁的、自包含的组件组成的程序的性能应该与手工编写的等效版本一样好,在手工编写的版本中,许多组件的功能被手工组合成一个整体实现。也就是说,程序员不应该为了获得性能而牺牲代码的清晰性或良好的软件工程实践——我们想要的是不影响性能的组合性。本文展示了如何在序列处理函数(包括数组处理等应用程序)领域为高级Haskell实现这一目标。
流融合的前期工作3.演示如何将一些高级序列处理函数自动转换为有效的实现。它在Haskell库中被用于操作字节数组、Unicode文本和未装箱的向量,效果非常好。然而,一些操作,如向量追加,在流融合框架中不能很好地执行。其他的,比如使用现代x86芯片上的SSE和AVX指令的SIMD计算,似乎根本不适合流融合框架。我们描述了广义流融合,它通过仔细选择流表示来解决这些问题。基准测试表明,使用我们的编译器和库编写的高级Haskell代码可以生成比编译器和手工向量化C更快的代码。
要求编译器能够将表示为高级Haskell代码的数值算法转换为严格的机器代码似乎是不合理的。编译器必须处理盒装数字类型,处理延迟求值,并消除中间数据结构。然而,Glasgow Haskell Compiler已经变得“足够聪明”,在许多领域,用于表示数值计算的Haskell库不再需要为了抽象而牺牲速度。
让这种牺牲变得不必要的关键发展是流融合。3.序列上的算法——无论它们是列表还是向量(数组)——都是使用折叠、映射和压缩等操作在函数式语言中自然表示的。尽管是高度模块化的,但这些操作会产生不必要的中间结构,导致代码效率低下。消除这些中间结构被称为森林砍伐或融合。方程定律,如映射f〇映射g≡映射(f〇g),允许消除其中一些中间结构;寻找更普遍的规律一直是大量研究的主题。
没有发现记录