Gem Parallel gem 实现从 3 个数组中分别取值进行科学计算的问题

paulshu · 2017年09月27日 · 最后由 paulshu 回复于 2017年10月06日 · 2600 次阅读

背景情况:

本人新人一枚,最近在做一个项目,需要从三个数组中(每个数组 4.6-6 万组数据),每个数组分别代表直角坐标中的 X,Y,Z,这里以 x_arr,y_arr,z_arr 说明。需要一次同时遍历三个数组,分别按顺序取出相应的 X,Y,Z 值后,代入到另一个函数进行计算。完成这样一次遍历要 1 分钟左右。

问题:

因时间花的比较多,为提高效率,想利用好计算机的多核 CPU 的能力。因此,我找到了Parallel这个 Gem, https://github.com/grosser/parallel

单线程我是这样写的

x_arr.zip(y_arr,z_arr) do |x,y,z|
  calculation(x,y,z)
end

然后我使用了Parallel,但无论如何也只能实现从其中一个数组中取值,首先将 x_arr 拆分成:x_arr1, x_arr2, x_arr3

多线程我是这样写的

Parallel.map([x_arr1, x_arr2, x_arr3]) do |x|
  calculation(x)
end

实测,会自动用到到三个核去计算,时间确实缩短了。但是问题来了 前面只取到了一个数组的值,但“y_arr,z_arr”没有取到,怎么试也不行,难道要重写 GEM 吗?还请大家分享一下经验,有什么办法可以解。十分感谢!

Parallel.map_with_index(x_arr) do |x, i|
  calculation(x, y_arr[i], z_arr[i])
end

这样试试

试了一下,确实可以,感谢啊! map_with_index 和 each_with_index 在 Parallel 中的用法主要区别在哪呢?

paulshu 回复

其实就是 map 和 each 的区别,with_index 就是在遍历的时可以获取当前索引

但我实际测试时,发现这两个还是有区别的。each_with_index 要配合使用 in_threads: 5,(数字可以修改),才能同时取到索引,而 map_with_index 就不需要,具体原因我不是很清楚。而且 each_with_index 在使用时还经常出现一些奇怪的问题,而使用 map_with_index 就比较正常一些。

问题已全部解决,测试 ok,分享一下经验 http://paulshu-blog.logdown.com/posts/2737227

向量化计算可能 SciRuby 是更好的选择,不过我一般用 Python 的 numpy,对应的 SciRuby 的 gem 应该是 https://github.com/SciRuby/rb-gsl

Python 是有很多成熟的包,numpy 之前有学习过,效率相当高,网上的资料也比较多,但 SciRuby 用的人好像并不多,在 ruby 上做科学计算的人太少了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号