1

非常に多数のファイルを同時に書き込みたい (たとえば 10000 ファイル)。そのためにマルチプロセッシングを使用できることがわかりました。これらのファイルを書き込むために、100 プロセスを使用することを任意に選択しました。使用するプロセスの最適な数を見つける方法があるかどうかを知る必要がありますか? また、このコードまたはすべてのプロセスが自動的に終了した後、クリーンアップを行う必要がありますか?

また、この多数のファイルを同時に書き込むためのより効率的な方法があるかどうかも知りたいです。

from multiprocessing import Pool

def write(x):
    fopen=open('file_'+str(x),'w')
    fopen.write('anything')
    fopen.close()

if __name__ == '__main__':
    pool = Pool(processes=100)              
    pool.map(write, range(10000))          
4

1 に答える 1

1

まず、純粋な I/O の場合、threadingは と同じかmultiprocessing、多くの場合それよりも優れています。また、「クリーンアップが必要ですか」という謎もありません。それで、あなたはそれをテストしたいかもしれません。

第二に、これを行うための最速の方法を知りたい場合、唯一の実際のオプションは、を使用してtimeit、またはおそらくシェルtimeまたは同等のものを使用してテストすることです。そして、あなたはすでにそれをやっているように聞こえます。システムについて読むことができる情報に基づいて理想的なプール サイズをプログラムで決定する方法を探している場合 (SSD 対 10K HD 対 5200 HD 対リモート共有、LAN 対 WAN、高速 LAN 対低速 LAN) 、SMB 対 NFS、Windows 対 POSIX など)、おそらくさまざまなマシンでテストし、統計分析を行う必要があります。また、その情報の一部は静的に利用できないため、実際にプロセスを開始してから、プール サイズを調整する必要があります。それは非常に複雑になるだろう — そして、ほとんどの場合、これらすべての作業は 10% の利益しか得られないと私は推測する.

ファイル I/O から最後の数パーセンテージ ポイントを本当に絞り出す必要がある場合は、レベルを 1 つか 2 つ下げる必要があるかもしれません。

少なくとも、Python および/または stdio バッファーを方程式から外して (ファイルが実際にこれほど小さいと仮定して)、 および を使用することをお勧めしos.openますos.write。文字列の代わりにバイトの raw バッファを作成することも役立つかもしれません (特にこれが Python 3 の場合)。実際にまったく同じものをすべてのファイル、または多くのファイルに書き込んでいる場合、同じバッファを使用すると、OS が同じものを複数のファイルに書き込んでいることを認識できる可能性があります。つまり、代わりにキャッシュが完璧になる可能性があります。完璧に近いです。

プラットフォーム固有の API にドロップダウンすることもできます。たとえば、Windows では、オーバーラップされた I/O を使用すると、OS が可能な限り効率的に書き込みをスケジュールできるようになり、完了を処理するために IOCP の周りにネイティブ スレッドプールを作成することで、書き込みスケジュールに加えてすべてのオーバーヘッドも削除されます。CreateFile( 、などにまたはWriteFileEx経由でアクセスできます。または、サンプル コードの「IOCP Python」をグーグルで検索します。特に、ほとんどが c10k ソケット サーバーを実行するように設計されているため、これらはすべて不完全または部分的に無関係ですが、少なくとも実証します。 MSDNと試行錯誤の助けを借りて、残りを自分で組み立てるのに十分です.)私はPOSIXで同等のものを考えることはできません.ctypeswin32apiaio_writeWriteFileEx、しかし、私の知る限り、実際の* nixプラットフォームでのパフォーマンスには役立ちません)。

または、ステップを上に移動することもできます。本当に同じデータをすべてのファイルまたは多数のファイルに書き込んでいるのであれば、それを 1 つのファイルに書き込んでから、OS にそのファイルをコピーするように依頼してみませんか? それはより良い仕事をすることができるかもしれません。

または、さらに単純で、はるかに高速に、それを 1 つのファイルに書き込み、残りをハード リンクまたはシンボリック リンクとして作成します。


最後のオプションについて尋ねたので:

リンクを作成する背後にある考え方は、ファイルを 1 つだけ作成し、そのファイルにアクセスするために 10000 の異なる名前を作成するというものです。

これは、1 つのファイルを編集すると、10000 個すべてが編集されることを意味します。それが望ましくない場合、リンクは適切ではありません。

ただし、必要に応じて、ハード リンクとシンボリック リンクの 2 種類の基本的なリンクがあります。

最新のファイルシステムでは、複数のディレクトリ エントリが同じファイルを指すことができます。ハード リンクの作成は、既存のファイルと同じファイルを指す別のディレクトリ エントリを作成する方法です。Python では、これをos.link. そう:

with open('file_0', 'w') as f:
    f.write('anything')
for i in range(1, 10000):
    os.link('file_0', 'file_{}'.format(i))

file_0これで、ファイルシステムにはから名前が付けられた 10000 のエントリがありますfile_9999が、それらはすべてディスク上の同じ実際のデータの名前です。1 つを編集すると、もう 1 つの 9999 がすべて変更されます。1 つを削除すると、残りの 9999 はまだ存在します。

ハード リンクには小さな問題がいくつかあり、大きな問題が 1 つあります。軽微な問題は、通常のファイル以外のもののハード リンクについてはプラットフォームごとに異なるルールがあり、通常はファイル システム間でハード リンクできないことです。主な問題は Windows です。まず、完全なサポートには Vista と NTFS 6、部分的なサポートには Win2000 と NTFS 4 が必要です。しかし、もっと重要なことに、 os.linkWindows には存在しません。ctypesそのため、 orを使用win32apiして基になるCreateHardLink関数を呼び出す (またはorコマンドsubprocessを実行する) 必要があります。mklinkfsutil

シンボリック リンクは上位レベルのアイデアです。これは、別のファイルをパスで参照する特別な種類のファイルです。これは、シンボリックリンク自体に関する情報を読み取ったり ( statvs.を参照lstat)、リンク情報を保持する tarball を作成したりできることを意味します。また、を削除するfile_0と、他のすべてのリンクが存在しないファイルを指す壊れたリンクになることも意味します。 . とにかく、Python では、os.symlink(上記とまったく同じコードで) それらを作成するために使用します。

シンボリック リンクにはハード リンクのほとんどの制限がありませんが、Windows ではさらに問題があります。Vista より前はシンボリック リンクがまったくない、プレーン ファイルとディレクトリのルールが異なる、トラバースできるリンク数の制限、特別な権限が必要です。管理者以外のユーザーが持っていないものなど。そしてもちろんos.symlink、Pythonからは使用できません。

Windows ショートカットや Mac エイリアスなど、シンボリック リンクに似ているが同一ではない機能を持つプラットフォーム固有のものもあります。

于 2013-02-18T20:18:34.657 に答える