我正在为ruby-fann创建输入,因为性能原因,尽可能多地在narray中进行操作。通常我操作2D 200x200浮点数阵列,并且需要重复处理数千次。
使用NArray,我获得了可接受的表现。然而,据我所知,我已经做了一些我想做的操作,我无法让NArray批量做事。这意味着我最终使用Ruby的循环控件来处理单个NArray条目。这对我的代码的性能有直接和不利的影响,我想知道我可以使用哪些解决方法或方法。我有能力,但不希望,分叉NArray并为我的工作添加一些功能。这对我来说并不合适,因为我需要的功能不够通用,无法进入该库。
我可能会考虑编写一个直接以某种方式使用NArray的原生扩展 - 关于如何做到这一点的指针是受欢迎的,我不确定如何从另一个引用一个本地扩展的gem。
我也非常感谢有关如何以不同方式构造代码,使Ruby部分更快,或利用任何NArray功能或相关库的任何见解或反馈。
我的两段代码非常相似,因此发布单一问题。
1)将浮点数矩阵限制在
范围内我目前正在做什么(简化):
# In reality, nn_input contains real-world data, and I want to
# re-normalise it, clipping high values to a maximum of 1.0
nn_input = NArray.float(200,200).random
nn_input *= 1.1
# The test for "anything needs clipping" is fast, the 200x200 loop is somewhat slower!
if (nn_input.gt 1.0).sum > 0
(0...200).each do |x|
(0...200).each do |y|
nn_input[x, y] = 1.0 if nn_input[x, y] > 1.0
end
end
end
2)根据平均值将大矩阵下采样到较小的矩阵(想想“图像重新调整大小”)
我目前正在做什么(简化):
# In reality, nn_input contains real-world data, and I want to
# downsize it, re-sampling a 200x200 array to a 20x20 one
large_input = NArray.float(200,200).random
small_output = NArray.float(20,20)
(0...20).each do |x|
(0...20).each do |y|
small_output[x, y] = large_input[x*10..x*10+9,y*10..y*10+9].mean
end
end
我在第二个例子中使用NArray的mean
方法,并且它比第一个例子更少,我最终为每个项目执行40000次小Ruby循环(因此超过2亿次整个数据集!)
在masa16的回复之后,这是一个非常快速的irb基准,显示了速度的差异:
irb
1.9.3-p327 :001 > require 'narray'
=> true
1.9.3-p327 :002 > t0 = Time.now; 250.times { nn_input = NArray.float(200,200).random() * 1.1; (0...200).each {|x| (0...200).each { |y| nn_input[x,y]=1.0 if nn_input[x,y]> 1.0 }} }; Time.now - t0
=> 9.329647
1.9.3-p327 :003 > t0 = Time.now; 250.times { nn_input = NArray.float(200,200).random() * 1.1; nn_input[nn_input.gt 1.0] = 1.0; }; Time.now - t0
=> 0.764973
因此,对于那个速度快10倍的小代码段,并且我通常运行时间不是250次,而是50,000次,在30分钟到1小时的运行时间内节省了大约需要3到4个小时的时间之前。
答案 0 :(得分:1)
1)
nn_input[nn_input.gt 1.0] = 1.0
2)
small_output = large_input.reshape(10,20,10,20).mean(0,2)
答案 1 :(得分:0)
您是否对代码进行了基准测试以确定是否存在瓶颈? 有没有什么方法可以将计算并行化以利用多核环境? 如果是这样,您是否考虑过使用JRuby来利用优秀的JVM多线程支持?
这些是我能想到的一些事情。可能只是你正在处理如此多的数据,你需要找到另一种解决方法。