繁体   English   中英

是否推荐使用函数式编程(F#)的时间序列实现?

[英]Is Time Series implementation using functional programming (F#) recommended?

我正在开发一个.NET项目,其中一部分我将操纵时间序列。

由于项目的主要部分已在C#中实现,因此我描绘了一个继承自SortedDictionary<DateTime,T>的面向对象设计。

然而,在过去的几年里,我一直爱着函数式编程,我认为由于这个组件将受到相当狂野和强烈的算法的影响,我愿意并行处理它,我很乐意拥有不可变结构。

我想用F#设计它,使用如下定义类型:

type TimeSeries<'t> = (DateTime * 't) seq

并继续下去。

它具有不可变的优点,并且使用F#的Async模块并行执行将非常简单。 我还可以使用F#的度量单位功能。

我有点害怕不得不在C#中使用计算结果,我想知道是否已经尝试过的人可以在实践中给我一些关于结果的反馈。

最后是否易于使用,还是从C#切换到F#太复杂了?

当时间序列变大时,集合是不可变的效率问题吗?

当我尝试划分元素时,我是否可以保持类型通用,或者我是否必须使用我的函数快速切换到TimeSeries<float>

如果我想在某些功能的时间序列上使用基于C#的算法,这会使整个想法变得无用吗?

您是否参考过有关时间序列功能实现效率的研究?

它具有不可变的优点,并且使用F#的异步模块并行执行将非常简单。

相反, seq很慢并且本质上是连续的。 SortedDictionary的字面F#等价物是Map但它不支持并行性。 Async模块适用于异步并发编程,但对并行性有害。

假设您希望按时间快速搜索并按顺序迭代但不是增量插入/删除,那么您需要一个KeyValuePair<DateTime, 'T>的排序数组,因为这提供了出色的局部性,因此,并行算法的缓存复杂性。 请注意,如果您避免变异,那么数组可以是纯函数。 请注意,F#2不会在DateTime键入specialize操作(如比较),因此您需要手动调用它们。

惯用的纯功能等价物是由时间划分的平衡搜索树:

type TimeSeries<'a> =
  | Leaf of DateTime * 'a
  | Branch of TimeSeries<'a> * DateTime * TimeSeries<'a>

这允许优雅的“并行”功能。 然而,实际情况是纯函数式编程对于多核并行性并不好,因为它无法提供有关局部性的任何保证,因此,纯函数式算法的高速缓存复杂性是不可预测的,性能通常很差。

当时间序列变大时,集合是不可变的效率问题吗?

完全取决于你想用它做什么。

您是否参考过有关时间序列功能实现效率的研究?

您还没有说过您打算实施的算法,甚至您想要快速执行的操作,因此很难以有用的方式讨论测量的性能。 在我的上网本上运行快速基准测试,在字典中插入1,000,000个绑定,表明可变的SortedDictionary需要5.2s,而不可变的Map需要11.8s,因此存在显着但不是很大的差异。 构建等效数组只需0.027秒。 迭代然后分别需要0.38s,0.20s和0.01s。

我有点害怕不得不在C#中使用计算结果,我想知道是否已经尝试过的人可以在实践中给我一些关于结果的反馈。

只需从F#代码中公开一个标准的.NET接口,这很简单。

有些要点需要注意:

  • 如果要将F#组件API公开给C#(或其他CLR语言),则应在F#组件的公共API中使用BCL(或OO类型)。 否则,您需要了解F#核心库用于实现F#的功能感的所有类型。 例如: FsharFunc
  • 对于不可变数据结构的并行处理(只读)很好,因为您确定没有人会从后台修改数据,因此您不需要进行锁定等。
  • 当你想让一个项目附加到一个列表的末尾时,不可变数据结构“可能”听起来不太好,理论上在不可变数据的情况下,它会将整个列表与新项目一起复制。 这通常是通过一些不可变数据结构的智能实现来避免的,例如clojure Persistent数据结构 ,而F#中没有这种结构

我希望以上几点可以帮助您确定最适合您具体实施的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM