3

私は問題を解決しようとしています。URLが多数(1万程度)あり、それらすべてからコンテンツをダウンロードする必要があります。これまで「forlinkinlinks:」ループでこれを行ってきましたが、時間がかかりすぎています。マルチスレッドまたはマルチプロセッシングのアプローチを実装する時が来たと思います。私の質問は、取るべき最善のアプローチは何ですか?

グローバルインタプリタロックについては知っていますが、私の問題はCPUバウンドではなくネットワークバウンドであるため、それが問題になるとは思いません。各スレッド/プロセスからメインスレッド/プロセスにデータを戻す必要があります。どんなアプローチを実装するのにも助けは必要ありません(いずれかのスレッドがタスクを完了したときに複数のスレッドを終了する)、どのアプローチを取るべきかについてのアドバイスが必要です。私の現在のアプローチ:

data_list = get_data(...)
output = []
for datum in data:
    output.append(get_URL_data(datum))
return output

他に共有状態はありません。

最善のアプローチは、すべてのデータを含むキューを作成し、入力キューから複数のワーカースレッドをポップして、URLデータを取得し、出力キューにプッシュすることだと思います。

私は正しいですか?足りないものはありますか?マルチスレッドコードを任意の言語で実装するのはこれが初めてであり、一般的に難しい問題であることを私は知っています。

4

3 に答える 3

5

特定のタスクについては、マルチプロセッシングワーカープールをお勧めします。プールを定義し、使用するプロセスの数(デフォルトではプロセッサコアごとに1つ)と、各作業単位で実行する関数を指定するだけです。次に、リスト内のすべての作業単位(この場合、これはURLのリストになります)を準備し、それをワーカープールに渡します。

出力は、元の配列内のすべての作業項目に対するワーカー関数の戻り値のリストになります。すべてのクールなマルチプロセッシングの良さは、バックグラウンドで発生します。もちろん、ワーカープールを操作する方法は他にもありますが、これは私のお気に入りの方法です。

ハッピーマルチプロセッシング!

于 2012-07-24T20:03:54.457 に答える
2

このようなIOバウンドタスクを実行するための最速かつ最も効率的な方法は、非同期イベントループです。libcurlはこれを行うことができ、pycurlと呼ばれるPythonラッパーがあります。「マルチ」インターフェースを使用すると、高性能のクライアントアクティビティを実行できます。私は1000回以上の同時フェッチを1回と同じ速さで実行しました。

ただし、APIは非常に低レベルであり、使用が困難です。ここに単純化ラッパーがあり、これを例として使用できます。

于 2012-07-24T20:12:48.607 に答える
1

あなたのユースケースで私が考えることができる最善のアプローチは、スレッドプールを使用してワークキューを維持することです。スレッドプール内のスレッドは、作業キューから作業を取得し、作業を実行してから、さらに作業を取得します。このようにして、URLで動作するスレッドの数を細かく制御できます。

したがって、WorkQueueを作成します。これは、基本的に、ダウンロードする必要のあるURLを含むリストです。

スレッドプールを作成します。これにより、指定した数のスレッドが作成され、WorkQueueから作業がフェッチされ、スレッドに割り当てられます。スレッドが終了して戻るたびに、作業キューにさらに作業があるかどうかを確認し、それに応じてそのスレッドに作業を再度割り当てます。また、作業がワークキューに追加されるたびに、スレッドがそれを空きスレッドに割り当てるようにフックを設定することもできます。

于 2012-07-24T20:09:14.610 に答える