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

Nas*_*ser 6 wolfram-mathematica

我之前没有使用过PackedArray,但是今天就开始考虑使用它们来阅读它们.

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

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

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

例如,这不会返回打包数组

a = Table[RandomReal[], {5}, {5}];
Developer`PackedArrayQ[a]
Run Code Online (Sandbox Code Playgroud)

但这样

a = RandomReal[1, {5, 5}];
Developer`PackedArrayQ[a]
Run Code Online (Sandbox Code Playgroud)

这样

a = Table[0, {5}, {5}];
b = ListConvolve[ {{0, 1, 0}, {1, 4, 1}, {0, 1, 1}}, a, 1];
Developer`PackedArrayQ[b]
Run Code Online (Sandbox Code Playgroud)

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

a = Table[0, {5}, {5}];
b = a.a;
Developer`PackedArrayQ[b]
Run Code Online (Sandbox Code Playgroud)

但元素乘法不是

b = a*a;
Developer`PackedArrayQ[b]
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢,

更新(1)

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

Bre*_*ion 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
  • 在研究性能时,请关注大型列表正在解压缩而不是小型列表的情况.除非小的是大循环.


Mik*_*rch 7

这只是Brett答案的附录:

SystemOptions["CompileOptions"]
Run Code Online (Sandbox Code Playgroud)

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

SetSystemOptions["CompileOptions" -> {"TableCompileLength" -> 20}]
Run Code Online (Sandbox Code Playgroud)

还要注意一些功能之间的差异对我来说至少看起来并不直观,所以每当我使用它们时我通常都要测试这些东西,而不是本能地知道什么是最好的:

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}
Run Code Online (Sandbox Code Playgroud)