PackedArrays是否有快速的产品操作? [英] Is there a fast product operation for PackedArrays?

查看:98
本文介绍了PackedArrays是否有快速的产品操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Mathematica中,包含所有机器尺寸整数或浮点数的矢量(或矩形数组)可以存储在压缩数组中.这些对象占用较少的内存,并且对它们的某些操作要快得多.

In Mathematica a vector (or rectangular array) containing all machine size integers or floats may be stored in a packed array. These objects take less memory, and some operations are much faster on them.

RandomReal尽可能生成一个压缩数组.打包数组可以使用Developer函数FromPackedArray

RandomReal produces a packed array when possible. A packed array can be unpacked with the Developer function FromPackedArray

考虑这些时间

lst = RandomReal[1, 5000000];

Total[lst] // Timing
Plus @@ lst // Timing

lst = Developer`FromPackedArray[lst];

Total[lst] // Timing
Plus @@ lst // Timing

Out[1]= {0.016, 2.50056*10^6}

Out[2]= {0.859, 2.50056*10^6}

Out[3]= {0.625, 2.50056*10^6}

Out[4]= {0.64, 2.50056*10^6}

因此,对于压缩数组,TotalPlus @@快许多倍,但对于非压缩数组几乎相同.请注意,Plus @@实际上在压缩数组上要慢一些.

Therefore, in the case of a packed array, Total is many times faster than Plus @@ but about the same for a non-packed array. Note that Plus @@ is actually a little slower on the packed array.

现在考虑

lst = RandomReal[100, 5000000];
Times @@ lst // Timing

lst = Developer`FromPackedArray[lst];
Times @@ lst // Timing

Out[1]= {0.875, 5.8324791357*10^7828854}

Out[1]= {0.625, 5.8324791357*10^7828854}

最后,我的问题是:在Mathematica中,有没有一种类似于Total的压缩数组列表产品的快速方法?

Finally, my question: is there a fast method in Mathematica for the list product of a packed array, analogous to Total?

我怀疑这可能是不可能的,因为数值误差与乘法复合.此外,该函数还必须能够返回非机器浮点数才有用.

I suspect that this may not be possible because of the way that numerical errors compound with multiplication. Also, the function will need to be able to return non-machine floats to be useful.

推荐答案

我还想知道是否存在与Total相等的乘法.

I've also wondered if there was a multiplicative equivalent to Total.

真的 不错的解决方案是

In[1]:= lst=RandomReal[2,5000000];
        Times@@lst//Timing
        Exp[Total[Log[lst]]]//Timing
Out[2]= {2.54,4.370467929041*10^-666614}
Out[3]= {0.47,4.370467940*10^-666614}

只要数字是正数,且大小不要太小, 那么四舍五入的错误还算不错. 关于评估期间可能发生的情况的猜测是:(1)假设数字为正浮点数,则可以将Log操作快速应用于压缩数组. (2)然后可以使用Total的压缩数组方法快速添加数字. (3)这只是需要非机械尺寸的浮子的最后一步.

As long as the numbers are positive and aren't too big or small, then the rounding errors aren't too bad. A guess as to what might be happening during evaluation is that: (1) Provided the numbers are positive floats, the Log operation can be quickly applied to the packed array. (2) The numbers can then be quickly added using Total's packed array method. (3) Then it's only the final step where a non-machine sized float need arise.

请参见此SO答案适用于正浮点数和负浮点数的解决方案.

See this SO answer for a solution that works for both positive and negative floats.

让我们快速检查一下该解决方案是否可与产生非机器大小答案的浮点数一起使用.与安德鲁(更快)compiledListProduct进行比较:

Let's quickly check that this solution works with floats that yield a non-machine sized answer. Compare with Andrew's (much faster) compiledListProduct:

In[10]:= compiledListProduct = 
          Compile[{{l, _Real, 1}}, 
           Module[{tot = 1.}, Do[tot *= x, {x, l}]; tot], 
           CompilationTarget -> "C"]

In[11]:= lst=RandomReal[{0.05,.10},15000000];
         Times@@lst//Timing
         Exp[Total[Log[lst]]]//Timing
         compiledListProduct[lst]//Timing
Out[12]= {7.49,2.49105025389*10^-16998863}
Out[13]= {0.5,2.4910349*10^-16998863}
Out[14]= {0.07,0.}

如果您选择较大的(>1)实数,则compiledListProduct将产生警告 CompiledFunction::cfne: Numerical error encountered; proceeding with uncompiled evaluation.,需要一些时间才能得出结果...

If you choose larger (>1) reals, then compiledListProduct will yield the warning CompiledFunction::cfne: Numerical error encountered; proceeding with uncompiled evaluation. and will take some time to give a result...

一个有趣的地方是SumProduct都可以接受任意列表. Sum正常工作

One curio is that both Sum and Product can take arbitrary lists. Sum works fine

In[4]:= lst=RandomReal[2,5000000];
         Sum[i,{i,lst}]//Timing
         Total[lst]//Timing
Out[5]= {0.58,5.00039*10^6}
Out[6]= {0.02,5.00039*10^6}

,但是对于较长的PackedArray,例如此处的测试示例,Product失败,因为自动编译的代码(在8.0版中)无法正确捕获下溢/上溢:

but for long PackedArrays, such as the test examples here, Product fails since the automatically compiled code (in version 8.0) does not catch underflows/overflows properly:

In[7]:= lst=RandomReal[2,5000000];
         Product[i,{i,lst}]//Timing
         Times@@lst//Timing
Out[8]= {0.,Compile`AutoVar12!}
Out[9]= {2.52,1.781498881673*10^-666005}

有用的WRI技术支持提供的解决方法是使用SetSystemOptions["CompileOptions" -> {"ProductCompileLength" -> Infinity}]关闭产品编译.另一种选择是使用lst=Developer`FromPackedArray[lst].

The work around supplied by the helpful WRI tech support is to turn off the product compilation using SetSystemOptions["CompileOptions" -> {"ProductCompileLength" -> Infinity}]. Another option is to use lst=Developer`FromPackedArray[lst].

这篇关于PackedArrays是否有快速的产品操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆