gpt4 book ai didi

ruby - 为什么 Enumerable#to_a 在 Ruby 版本 >= 1.9.3 中以这种方式运行?

转载 作者:太空宇宙 更新时间:2023-11-03 17:34:22 25 4
gpt4 key购买 nike

这是 MRI 中的错误还是对此行为有很好的解释?

def pmap(enum)
return to_enum(:pmap, enum) unless block_given?
enum.map { |e| Thread.new { yield e } }.map(&:value)
end

# Returns elements in order, as expected.
pmap(1..10) { |e| e } #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Returns elements in nondeterministic order on MRI >= 1.9.3.
# Works as expected on JRuby, Rubinius, and earlier versions of MRI.
pmap(1..10).to_a #=> [7, 2, 3, 4, 6, 5, 9, 8, 10, 1]

第一个 map 应该返回一个线程数组,第一个线程产生 1,等等。

第二个 map 应该收集每个线程的值。

我不明白为什么返回的结果会乱序。

我看过 what I believe is the relevant code in enum.c ,但我仍然不明白为什么会这样。我怀疑这是性能优化出了问题。还是我对 Enumerable#to_a 期望过高(具体来说,它不会改变可枚举的顺序)?

最佳答案

line 3将枚举映射到立即返回且独立于线程 block 完成的线程。 .value blocks on the completion of the thread在创建很久之后。

这表明对 Thread block 的实际求值并未按顺序发生,但 Thread.new 初始化的结果确实发生得足够快以产生有序的 Thread 实例。

def pmap(enum)
return to_enum(:pmap, enum) unless block_given?
enum.map { |e| Thread.new { sleep(Random.rand); p e; yield e } }.map(&:value)
end

pmap(1..10) { |e| e }

1
2
5
6
8
3
7
9
4
10

以下是如何通过 to_enum 对并行执行的结果进行排序,它使用纤程来执行 block :

def pmap(enum)
return to_enum(:pmap, enum) unless block_given?
enum.each_with_index.map { |e,i| Thread.new { sleep(Random.rand); p e; yield ({index: i, value:e }) } }.map(&:value)
end

p to_enum(:pmap, 1..10).sort_by { |hash| hash[:index] }.map { |hash| hash[:value] }
#p pmap(1..10) { |x| x }

关于ruby - 为什么 Enumerable#to_a 在 Ruby 版本 >= 1.9.3 中以这种方式运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22109717/

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