免責事項
地図の一部をある土地から別の土地に移すために、友人が地理的な必要性が生まれました。 彼はイルカの習慣からこれをしましたが、私はPythonを実際に試してみたかったのですが、私は専門家ではありません。
練習する
実際にアルゴリズムを翻訳することは非常に簡単であることが判明しましたが、その作業の速度には多くのことが望まれていませんでした。
最初のステップはPsycoで、処理を6倍高速化しました。
アルゴリズムを変更せずに最良の結果を得ることができなくなったため、ブルートフォース方式(タスクの並列化)が使用されました。
並列Pythonモジュールが見つかりました。 接続は非常に簡単であることがわかりました。
最初に
import pp
、次に(最初のオプション):
ppservers =() job_server = pp.Server(ppservers = ppservers) job_server.set_ncpus(2) 「starting pp with」、job_server.get_ncpus()、「workers」を印刷します jobs = [job_server.submit(tighina_check、()、(find_geo_coords、compare、get_dist_bearing、)、( "math"、))for i in range(3)] ジョブインジョブの場合: 仕事() job_server.print_stats()
コードは原則としてそれ自体を語っています-ローカルサーバーのみを使用します(一般的に、モジュールはネットワークサーバーに並列化することを可能にします)、2つのプロセッサで実行し、呼び出す関数と依存する関数を示し、数学をインポートし、3つのタスクを実行します、最後に統計を出力します。
最初の待ち伏せはサイコをオフにし、それが再び開始位置に私たちを投げた。
ソリューションは明らかでした-ジョブを作成するときにサイコのインポートを追加します
jobs = [job_server.submit(tighina_check, (), (find_geo_coords, compare, get_dist_bearing,), ("math", "psyco", )) for i in range(3)]
そして、すでにtighina_checkでpsyco.fullを呼び出します:
def tighina_check(): psyco.full() #そしてここにたくさんの数学があります
2番目の問題は非常に予想外でした。
tighina_checkのコードは、もともと「from from math import sin、pow、cos、asin、sqrt、fabs、acos」という形式のインポート用にシャープ化されました。 しかし、それはppの下では機能しませんでした、なぜなら ジョブの作成時に指定されたモジュールを使用して、関数のランタイムのみを作成します。 罪のすべての呼び出しをmath.sinなどにやり直すことは論理的でした。 ここで少し困惑が生じました。2番目の呼び出し形式で数学関数を集中的かつ絶えず使用すると、1.3〜1.4倍の速度低下につながりました。
解決策は、各ジョブの開始時に必要な機能をグローバルスコープに手動でインポートすることでした。
def tighina_check(): psyco.full() math_func_imports = ['sin'、 'cos'、 'asin'、 'acos'、 'sqrt'、 'pow'、 'fabs'] math_func_importsのfuncの場合: setattr(__ builtins __、func、getattr(math、func))
それから、psycoを使用してpp自体を高速化するのがいいと思いました。 これを行うには、キットから小さなpyworker.pyにパッチを適用して、先頭に追加する必要があります。
輸入サイコ psyco.full()
そして交換
eval(__ fobj)に
exec __fobj
同時に、ジョブを作成するときにpsycoをインポートする必要はありません。したがって、job'eでpsyco.full()を呼び出します。
残りは、必要なプロセッサ数の選択です
結果は何ですか?
100件のジョブが開始されました。
元のバージョン(並列化なし、psychoのみ)
連続した100ジョブ257秒
2プロセッサ(pp、psyco)
2人のワーカーでppを開始 ジョブ実行統計: 仕事数| すべての仕事の割合| 仕事時間合計| ジョブあたりの時間| ジョブサーバー 100 | 100.00 | 389.8933 | 3.898933 | ローカル サーバーの作成195.12789011からの経過時間
4プロセッサー(pp、psyco)
4人のワーカーでppを開始 ジョブ実行統計: 仕事数| すべての仕事の割合| 仕事時間合計| ジョブあたりの時間| ジョブサーバー 100 | 100.00 | 592.9463 | 5.929463 | ローカル サーバー作成からの経過時間148.77167201
私はこれ以上テストしたくありませんでしたが、2つのコアがあり、それぞれハイパートレッド(4つのジョブを意味する)が最適なオプションであるように思われました。 しかし、好奇心が取り上げられました(そして判明したように-無駄ではありません):
8プロセッサー(pp、psyco)
8人のワーカーでppを開始 ジョブ実行統計: 仕事数| すべての仕事の割合| 仕事時間合計| ジョブあたりの時間| ジョブサーバー 100 | 100.00 | 1072.3920 | 10.723920 | ローカル サーバー作成からの経過時間137.681350946
16プロセッサ(pp、psyco)
16人のワーカーでppを開始 ジョブ実行統計: 仕事数| すべての仕事の割合| 仕事時間合計| ジョブあたりの時間| ジョブサーバー 100 | 100.00 | 2050.8158 | 20.508158 | ローカル サーバー作成からの経過時間133.345046043
32個のプロセッサー(pp、psyco)
32人のワーカーでppを開始 ジョブ実行統計: 仕事数| すべての仕事の割合| 仕事時間合計| ジョブあたりの時間| ジョブサーバー 100 | 100.00 | 4123.8550 | 41.238550 | ローカル サーバー作成からの経過時間136.022897005
T.O. 最良の場合、133秒対元の場合の257 =並列化のみによる特定のタスクの1.93倍の加速。
100個のジョブはすべて互いに独立しており、互いに「通信」する必要がないため、タスクが容易になり、速度が向上することに注意してください。
要約コード例:
ppservers =() job_server = pp.Server(ppservers = ppservers) job_server.set_ncpus(16) 「starting pp with」、job_server.get_ncpus()、「workers」を印刷します jobs = [job_server.submit(tighina_check、()、(find_geo_coords、compare、get_dist_bearing、)、( "math"、))for i in range(3)] ジョブインジョブの場合: 仕事() job_server.print_stats()
def tighina_check(): math_func_imports = ['sin'、 'cos'、 'asin'、 'acos'、 'sqrt'、 'pow'、 'fabs'] math_func_importsのfuncの場合: setattr(__ builtins __、func、getattr(math、func)) #そしてここにたくさんの数学があります