Ruby NArray针对下采样和条件变化的优化

Ruby NArray针对下采样和条件变化的优化,ruby,narray,Ruby,Narray,我正在为ruby fann创建输入,出于性能原因,在narray中尽可能多地进行操作。通常,我操作的是2D 200x200浮点数组,需要重复处理1000多次 仅使用NArray,我就可以获得可接受的性能。然而,就我所能看到的,我遇到了一些我想做的操作,我无法让NArray批量做事情。这意味着我最终使用Ruby的循环控件来处理单个NArray条目。这对我的代码的性能有直接和有害的影响,我想知道我有什么解决办法或方法。我能够,但不希望,分叉NArray并为我的工作添加一些特性。这并不适合我,因为我需

我正在为ruby fann创建输入,出于性能原因,在narray中尽可能多地进行操作。通常,我操作的是2D 200x200浮点数组,需要重复处理1000多次

仅使用NArray,我就可以获得可接受的性能。然而,就我所能看到的,我遇到了一些我想做的操作,我无法让NArray批量做事情。这意味着我最终使用Ruby的循环控件来处理单个NArray条目。这对我的代码的性能有直接和有害的影响,我想知道我有什么解决办法或方法。我能够,但不希望,分叉NArray并为我的工作添加一些特性。这并不适合我,因为我需要的特性不够通用,无法进入该库

我可能会考虑编写一个直接使用NARDATA的本机扩展——关于如何做到这一点的指针将是受欢迎的,我不知道如何引用另一个自扩展的GEM。

我也非常感谢任何关于如何以不同的方式构造代码的见解或反馈,以使Ruby部件更快,或利用任何NArray特性或相关库

我的两段慢代码非常相似,因此只提出了一个问题

1) 将浮动矩阵限制在一个范围内

我目前正在做的事情(简化):

2) 根据平均值将一个较大的矩阵向下采样为较小的矩阵(考虑“图像重新大小”)

我目前正在做的事情(简化):

在第二个示例中,我使用了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次,而是50000次,这为我节省了大约30分钟到1小时的运行时间,而之前需要3到4个小时。

您是否对代码进行了基准测试,以确定是否存在任何瓶颈?
有没有什么方法可以利用多核环境并行计算? 如果是这样,您是否考虑过使用JRuby来利用优秀的JVM多线程支持


这些是我脑海中能想到的一些事情。可能只是因为您处理的数据太多,需要找到另一种解决方法。

您是否对代码进行了基准测试,以确定是否存在瓶颈?
有没有什么方法可以利用多核环境并行计算? 如果是这样,您是否考虑过使用JRuby来利用优秀的JVM多线程支持

这些是我脑海中能想到的一些事情。可能只是因为您处理的数据太多,需要找到另一种解决方法。

1)

nn_输入[nn_输入.gt 1.0]=1.0

(二)

小输出=大输入。整形(10,20,10,20)。平均值(0,2)

1)

nn_输入[nn_输入.gt 1.0]=1.0

(二)

小输出=大输入。整形(10,20,10,20)。平均值(0,2)

根据code diff,我非常确定问题出在我发布的示例代码中(特别是示例1),因此我还没有尝试过基准测试或概要文件。稍后我将尝试做一些基本的事情,并在上面发布结果。我使用的是1.9.3,我使用的其他一些库不适用于JRuby AFAIK(可能是ruby fann和ruby fftw)。MRI Ruby中的AFAIK多线程无法让我访问更多的内核。我从code diff中非常确定问题出在我发布的示例代码中(特别是示例1),因此还没有尝试过基准测试或配置文件。稍后我将尝试做一些基本的事情,并在上面发布结果。我使用的是1.9.3,我使用的其他一些库不适用于JRuby AFAIK(可能是ruby fann和ruby fftw)。MRI Ruby中的AFAIK多线程无法让我访问更多的内核。对(1)的回答我没有预料到,非常酷!非常感谢。答案(1)我没想到,非常酷!非常感谢。
  # 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
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