在PackedArray上,寻找使用它们的建议

时间:2012-01-08 04:23:37

标签: wolfram-mathematica

我以前没有使用过PackedArray,但是刚刚开始考虑使用它们来阅读今天的讨论。

我所拥有的是所有实数的大尺寸1D和2D矩阵,没有符号(它是有限差分的PDE求解器),所以我认为我应该利用PackedArray。

我有一个初始化函数,我分配所需的所有数据/网格。所以我去了ToPackedArray使用它们。它似乎要快一点,但我需要做更多的性能测试,以便更好地比较前后的速度,并比较RAM的使用情况。

但是当我看到这个时,我注意到M中的某些操作已经自动返回PackedArray中的列表,而有些则没有。

例如,返回打包数组

a = Table[RandomReal[], {5}, {5}];
Developer`PackedArrayQ[a]

确实

a = RandomReal[1, {5, 5}];
Developer`PackedArrayQ[a]

确实

a = Table[0, {5}, {5}];
b = ListConvolve[ {{0, 1, 0}, {1, 4, 1}, {0, 1, 1}}, a, 1];
Developer`PackedArrayQ[b]

并且矩阵乘法确实在打包数组中返回结果

a = Table[0, {5}, {5}];
b = a.a;
Developer`PackedArrayQ[b]

但元素明智的乘法

b = a*a;
Developer`PackedArrayQ[b]

我的问题:是否有一个列表哪个文件哪个M命令返回PackedArray而不是? (假设数据符合要求,例如Real,不混合,没有符号等。)

另外,一个小问题,您认为在调用ToPackedArray之前,首先检查创建的列表/矩阵是否已经打包会更好吗?我认为在已经打包的列表上调用ToPackedArray将不会花费任何费用,因为呼叫将立即返回。

感谢,

更新(1)

只是想提一下,我发现在演示CDF中不允许使用PackedArray符号,因为我在上传一个时遇到错误。所以,不得不删除我的所有包装代码。由于我主要编写演示,现在这个主题对我来说只是学术兴趣。但是要感谢大家的时间和好的答案。

3 个答案:

答案 0 :(得分:9)

没有全面的清单。指出一些事情:

  • 打包数组的基本操作将趋于保持打包状态:
 
    In[66]:= a = RandomReal[1, {5, 5}];

    In[67]:= Developer`PackedArrayQ /@ {a, a.a, a*a}

    Out[67]= {True, True, True}
  • 请注意,我的版本(8.0.4)不会解包元素乘法。

  • Table是否会产生打包数组取决于元素数量:

 
    In[71]:= Developer`PackedArrayQ[Table[RandomReal[], {24}, {10}]]

    Out[71]= False

    In[72]:= Developer`PackedArrayQ[Table[RandomReal[], {24}, {11}]]

    Out[72]= True

    In[73]:= Developer`PackedArrayQ[Table[RandomReal[], {25}, {10}]]

    Out[73]= True
  • On["Packing"]会打开消息,让您知道什么时候打开包装:
 
    In[77]:= On["Packing"]

    In[78]:= a = RandomReal[1, 10];

    In[79]:= Developer`PackedArrayQ[a]

    Out[79]= True

    In[80]:= a[[1]] = 0 (* force unpacking due to type mismatch *)

       Developer`FromPackedArray::punpack1: Unpacking array with dimensions {10}. >>

    Out[80]= 0
  • 执行每个元素检查的操作通常会解压缩数组
    In[81]:= a = RandomReal[1, 10];

    In[82]:= Position[a, Max[a]]

       Developer`FromPackedArray::unpack: Unpacking array in call to Position. >>

    Out[82]= {{4}}
  • 在已打包的列表上调用ToPackedArray的罚款足够小,我不会太担心:

    In[90]:= a = RandomReal[1, 10^7];

    In[91]:= Timing[Do[Identity[a], {10^5}];]

    Out[91]= {0.028089, Null}

    In[92]:= Timing[Do[Developer`ToPackedArray[a], {10^5}];]

    Out[92]= {0.043788, Null}

  • 前端更喜欢打包到解压缩的数组,这可以在处理DynamicManipulate时显示:
    In[97]:= Developer`PackedArrayQ[{1}]

    Out[97]= False

    In[98]:= Dynamic[Developer`PackedArrayQ[{1}]]

    Out[98]= True
  • 在研究性能时,请关注大型列表正在解压缩的情况,而不是小型的。除非那些小的是大圈。

答案 1 :(得分:7)

这只是Brett's answer的附录:

SystemOptions["CompileOptions"]

将为您提供函数将返回打包数组的长度。因此,如果您确实需要打包一个小列表,作为使用Developer`ToPackedArray的替代方法,您可以为其中一个编译选项临时设置一个较小的数字。 e.g。

SetSystemOptions["CompileOptions" -> {"TableCompileLength" -> 20}]

另外请注意一些功能之间的差异,这对我来说至少看起来并不直观,所以每当我使用这些功能时,我通常都要测试这些东西,而不是本能地知道哪种方法效果最好:

f = # + 1 &;
g[x_] := x + 1;
data = RandomReal[1, 10^6];

On["Packing"]
Timing[Developer`PackedArrayQ[f /@ data]]
{0.131565, True}


Timing[Developer`PackedArrayQ[g /@ data]]
Developer`FromPackedArray::punpack1: Unpacking array with dimensions {1000000}.
{1.95083, False}

答案 2 :(得分:4)

Brett回答的另一个补充:如果列表是一个打包数组,那么ToPackedArray非常快,因为这很早就检查过了。你也可能觉得这很有价值:

http://library.wolfram.com/infocenter/Articles/3141/

一般情况下,对于数字的东西,请寻找Rob Knapp和/或Mark Sofroniou的谈话。

当我开发数字代码时,我编写函数然后使用On [“Packing”]来确保所有内容都打包需要打包。

关于Mike的答案,已经引入了阈值,因为对于小东西而言存在开销。阈值是硬件相关的。编写一个根据计算机上完成的测量来设置这些阈值的函数可能是一个想法。