3

できるだけ早く実行するために、この1週間ほどで書き直したコードのチャンクがあります。

コードは回折レーザービームをモデル化しており、その本質は、多くの2D 1280*1280スライスにわたる640*640カーネルの畳み込みです。各スライスはビーム軸に沿った新しい位置です。

最適化の第1段階は関数のコンパイルであり、第2段階はMathematicaが大量のデータのリストを操作するのが好きであることを学びました。つまり、スライスを次々に渡すのではなく、一度に多くのレイヤーの3D空間を渡します。

しかし、これは私のRAMを食べました!

これが私の現在の設定です:

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}];

いくつかの説明:

  • 可能な限りコンパイルできるようにしたいので、作業は2つの機能に分割されます。
  • Z値はリストのリストに分割され、関数が一度に複数のレイヤーを評価するようにします。

いくつかの質問:

  • これをどのように速くしますか?
  • そのまま実行すると、両方のコアが使用されますが、1つのmathematicaカーネルによって使用されます。ParallelTableで実行すると、複数のカーネルが実行されますが、RAMの消費量が多くなり、最終的には遅くなります。
  • できるだけ多くのコアで実行できるようにしたいと思います-LightweightGridを実行しています-これを行うにはどうすればよいですか?
  • 異なる次元のコンパイル済み関数リストを渡せないのはなぜですか?
4

2 に答える 2

1

並列化も C コンパイル (Windows 64 ビットで VC++Express によって強化された Equation.com の gcc 4.7 を使用) も、タイミングを改善しません。

このコードの実行には約 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

すべてを 1 つの関数にコンパイルするのは遅くなります (8.1 秒):

$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

通常、いつ ParallelTable とその仲間が本当に役立つのかを理解するのはそれほど簡単ではありません。問題、サイズ、Mathematica のバージョンなどによって異なります。

于 2011-11-08T23:39:53.873 に答える