Wolfram mathematica 优化大型模型-尝试利用并行性

Wolfram mathematica 优化大型模型-尝试利用并行性,wolfram-mathematica,mathematical-optimization,mathematica-8,Wolfram Mathematica,Mathematical Optimization,Mathematica 8,在过去一周左右的时间里,我一直在重新编写大量代码,以使其尽快运行 该代码正在模拟衍射激光束,其本质是640*640内核在许多2D 1280*1280切片上的卷积-每个切片是沿光束轴的一个新位置 优化的第一个阶段是编译我的函数,第二个阶段是学习Mathematica喜欢处理大量的数据列表,因此一次向它传递多个层的3D空间,而不是一个接一个的切片 然而,这吃了我的公羊 以下是我当前的设置: Func2[K_ , ZRange_] := Module[{layers = Dimensions[ZRan

在过去一周左右的时间里,我一直在重新编写大量代码,以使其尽快运行

该代码正在模拟衍射激光束,其本质是640*640内核在许多2D 1280*1280切片上的卷积-每个切片是沿光束轴的一个新位置

优化的第一个阶段是编译我的函数,第二个阶段是学习Mathematica喜欢处理大量的数据列表,因此一次向它传递多个层的3D空间,而不是一个接一个的切片

然而,这吃了我的公羊

以下是我当前的设置:

Func2[K_ , ZRange_] :=
Module[{layers = Dimensions[ZRange][[1]]},
x = ConstantArray[Table[x, {x, -80, 80, 0.125}, {y, -80, 80, 0.125}], {layers}];
y = ConstantArray[Table[y, {x, -80, 80, 0.125}, {y, -80, 80, 0.125}], {layers}];
z = Table[ConstantArray[z, {1281, 1281}], {z, ZRange}];

UTC = Func3[x, y, z];

Abs[ListConvolve[K, #] & /@ UTC]
] 


Func3 = Compile[{{x, _Real}, {y, _Real}, {z, _Real}},
Module[{Sr2R2 = Sqrt[x^2 + y^2 + z^2]},
0.5 (1. + z/Sr2R2) Exp[2 \[Pi] I (Sr2R2 - z)]/Sr2R2],
RuntimeAttributes -> {Listable},
CompilationTarget -> "C"
];


ZRangeList = {{20., 19., 18., 17., 16., 15., 14., 13., 12., 11.},
               {10., 9., 8., 7., 6., 5., 4., 3., 2., 1.}};


results = Table[Func2[kernel, ZList], {ZList, ZRangeList}];
一些解释:

  • 这项工作分为两个函数,因为我希望能够尽可能多地编译
  • Z值被拆分为一个列表列表,以使函数同时计算多个层
一些问题:

  • 你如何让这更快
  • 当按原样运行时,我的两个内核都被一个mathematica内核使用。如果我用ParallelTable运行它,它会运行多个内核,但会消耗更多的RAM,最终速度会变慢
  • 我希望能够在尽可能多的内核上运行它-我有一个LightweightGrid运行-我如何才能做到这一点
  • 为什么我不能传递不同维度的编译函数列表

    • 突然向我扑来的东西是

      Abs[listcolvalve[K,#]&UTC] 可以做成 平行图[Abs@ListConvolve[K,#]&UTC]

      然而,我真的很惊讶并行表比普通表慢,因为这只是在两种情况下的情况:并行化比执行任务更昂贵,或者并行化需要子内核之间的太多通信

      并行化后,您是否分发了定义?例如,对于以上内容,您应该在开始之前先启动内核,然后分发K的定义(UTC不需要分发,因为它实际上不在子内核中使用,而是在子内核中使用。看看您是否可以利用Share[]来减少内存负载

      你有没有想过用CUDA来做这件事?似乎非常适合你在函数中做的简单数值计算

      还要注意,您不断地创建这个表:table[x,{x,-80,80,0.125},{y,-80,80,0.125}],为什么不将其作为一个变量,并为该变量的值创建一个常量呢? 你在每一个上面都浪费了0.2秒

      最后,一个小小的怪癖:当你试图优化时,划分总是一件可怕的事情——它很耗时:

      Module[{Sr2R2 = Sqrt[x^2 + y^2 + z^2]},
             0.5 (1. + z/Sr2R2) Exp[2 \[Pi] I (Sr2R2 - z)]/Sr2R2]
      
      可以使头发更好(请随意检查我的数学):


      既不是并行化,也不是C编译 (使用equation.com中的GCC4.7,并在Windows 64位上使用VC++Express进行增强)确实改善了计时

      运行此代码大约需要6.5秒:

          $start = AbsoluteTime[];
      Func2[K_, ZRange_] := 
       Module[{layers = Dimensions[ZRange][[1]], x, y, z, UTC, tx, ty, t1},
        tx = Table[x, {x, -80, 80, 0.125}, {y, -80, 80, 0.125}];
        ty = Table[y, {x, -80, 80, 0.125}, {y, -80, 80, 0.125}];
        x = ConstantArray[tx, {layers}];
        y = ConstantArray[ty, {layers}];
        z = Table[ConstantArray[z, {1281, 1281}], {z, ZRange}];
        t1 = AbsoluteTime[];
        UTC = Func3[x, y, z];
        Print["Func3 time = ", AbsoluteTime[] - t1];
        Abs[ListConvolve[K, #] & /@ UTC]]
      Func3 = Compile[{{x, _Real, 3}, {y, _Real, 3}, {z, _Real, 3}}, 
         Module[{Sr2R2 = Sqrt[x^2 + y^2 + z^2]}, 
          0.5 (1. + z/Sr2R2) Exp[2 \[Pi] I (Sr2R2 - z)]/Sr2R2]];
      ZRangeList = {{20., 19., 18., 17., 16., 15., 14., 13., 12., 
          11.}, {10., 9., 8., 7., 6., 5., 4., 3., 2., 1.}};
      SeedRandom[1]; kernel = RandomReal[{-1, 1}, {640, 640}];
      results1 = Table[Func2[kernel, ZList], {ZList, ZRangeList}];
      AbsoluteTime[] - $start
      
      将所有内容编译成一个函数的速度较慢(8.1秒):

      通常,要弄清楚什么时候ParallelTable和朋友真的有帮助并不容易。 这取决于问题的大小,Mathematica verison,等等

          $start = AbsoluteTime[];
      Func2[K_, ZRange_] := 
       Module[{layers = Dimensions[ZRange][[1]], x, y, z, UTC, tx, ty, t1},
        tx = Table[x, {x, -80, 80, 0.125}, {y, -80, 80, 0.125}];
        ty = Table[y, {x, -80, 80, 0.125}, {y, -80, 80, 0.125}];
        x = ConstantArray[tx, {layers}];
        y = ConstantArray[ty, {layers}];
        z = Table[ConstantArray[z, {1281, 1281}], {z, ZRange}];
        t1 = AbsoluteTime[];
        UTC = Func3[x, y, z];
        Print["Func3 time = ", AbsoluteTime[] - t1];
        Abs[ListConvolve[K, #] & /@ UTC]]
      Func3 = Compile[{{x, _Real, 3}, {y, _Real, 3}, {z, _Real, 3}}, 
         Module[{Sr2R2 = Sqrt[x^2 + y^2 + z^2]}, 
          0.5 (1. + z/Sr2R2) Exp[2 \[Pi] I (Sr2R2 - z)]/Sr2R2]];
      ZRangeList = {{20., 19., 18., 17., 16., 15., 14., 13., 12., 
          11.}, {10., 9., 8., 7., 6., 5., 4., 3., 2., 1.}};
      SeedRandom[1]; kernel = RandomReal[{-1, 1}, {640, 640}];
      results1 = Table[Func2[kernel, ZList], {ZList, ZRangeList}];
      AbsoluteTime[] - $start
      
      $start = AbsoluteTime[]; 
      CFunc2 = Compile[{{kern, _Real, 2}, {ZRange, _Real, 1}}, 
          Module[{layers = Length[ZRange], x, y, z, UTC, ty, Sr2R2}, 
           ty = Table[y, {x, -80, 80, 0.125}, {y, -80, 80, 0.125}]; 
            x = Table[x, {layers}, {x, -80, 80, 0.125}, {y, -80, 80, 0.125}]; 
            y = Table[y, {layers}, {x, -80, 80, 0.125}, {y, -80, 80, 0.125}]; 
            z = Table[ConstantArray[z, {1281, 1281}], {z, ZRange}]; 
            Sr2R2 = Sqrt[x^2 + y^2 + z^2]; UTC = 0.5*(1. + z/Sr2R2)*
              (Exp[2*Pi*I*(Sr2R2 - z)]/Sr2R2); 
            Abs[(ListConvolve[kern, #1] & ) /@ UTC]]]; 
      ZRangeList = {{20., 19., 18., 17., 16., 15., 14., 13., 12., 11.}, 
          {10., 9., 8., 7., 6., 5., 4., 3., 2., 1.}}; 
      SeedRandom[1]; kernel = RandomReal[{-1, 1}, {640, 640}]; 
      results = Table[CFunc2[kernel, ZList], {ZList, ZRangeList}]; 
      AbsoluteTime[] - $start