gpt4 book ai didi

rust - Rust 中的多重特化、迭代器模式

转载 作者:行者123 更新时间:2023-11-29 07:55:39 28 4
gpt4 key购买 nike

学习 Rust(耶!),我正在尝试理解某些迭代器模式所需的预期惯用编程,同时获得最佳性能。注意:不是 Rust 的 Iterator 特性,只是我编写的一个方法接受闭包并将其应用于我从磁盘/内存中提取的一些数据。

我很高兴看到 Rust(+LLVM?)采用了我为稀疏矩阵条目编写的迭代器,以及用于执行稀疏矩阵向量乘法的闭包,写为

iterator.map_edges({ |x, y| dst[y] += src[x] });

并在生成的代码中内联闭包的主体。它进行得相当快。 :D

如果我创建两个这样的迭代器,或者第二次使用第一个(不是正确性问题)每个实例都会减慢很多(在这种情况下大约是 2 倍),大概是因为优化器不再选择进行特化,因为多个调用站点,您最终会为每个元素执行一个函数调用。

我试图了解是否有惯用模式可以在不牺牲性能的情况下保持愉快的体验(至少我喜欢它)。我的选择似乎是(没有满足这个限制):

  1. 接受不可靠的性能(慢 2 倍并不致命,但也没有奖励)。
  2. 要求用户提供面向批处理的闭包,以便对小批量数据的迭代器进行操作。这暴露了迭代器的一些内部结构(数据被很好地压缩,用户需要知道如何解包它们,或者迭代器需要在内存中暂存一个解包的批处理)。
  3. 使 map_edges 在实现假设的 EdgeMapClosure 特征的类型中通用,并要求用户为他们想要内联的每个闭包实现这样的类型。未经测试,但我猜这会向 LLVM 公开不同的方法,每个方法都得到很好的内联。缺点是用户必须编写自己的闭包(打包相关状态等)。
  4. 可怕的 hack,比如制作不同的方法 map_edges0map_edges1,...。或者添加一个通用参数,程序员可以使用它来使方法不同,但否则会被忽略。

非解决方案包括“just use for pair in iterator.iter() {/* */}”;这是数据/任务并行平台的准备工作,我希望能够捕获/移动这些闭包到工作线程,而不是捕获主线程的执行。也许我应该使用的模式是编写上面的内容,将放在一个 lambda/闭包中,然后将它发送出去?

在一个完美的世界中,如果有一种模式可以使源文件中每次出现的 map_edges 都在二进制文件中产生不同的专用方法,而不强制整个项目是在一些可怕的水平上进行了优化。我正在摆脱与托管语言和 JIT 的不愉快关系,在这些语言和 JIT 中,泛型是(我知道的)实现这一目标的唯一方法,但 Rust 和 LLVM 看起来足够神奇,我认为可能有一个好方法。 Rust 的迭代器如何处理这个以内联它们的闭包体?或者他们不(他们应该!)?

最佳答案

看来问题已通过 Rust 概述的新闭包方法解决了

http://smallcultfollowing.com/babysteps/blog/2014/11/26/purging-proc/

简而言之,当您使用新的闭包特征使实现泛化时,上面的选项 3(使函数相对于新的闭包类型泛化)现在透明地实现了。 Rust 会在幕后为您生成类型。

关于rust - Rust 中的多重特化、迭代器模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26303090/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com