4

単一の巨大なバイナリ ファイルに含まれる一連の画像 (~10^7) があります。すでに持っている機能を使って効率的に読み込んで分析したい。コード内のそのユーザー関数の各反復にfooは約 0.1 秒かかるため、コードがデータベース全体を読み取る単純な for ループを使用してデータベース全体を処理するには数日かかります。

... 
for image_number=1:N
     offset_in_bytes = npoints_per_image*element_size*(image_number-1);
     fseek(fid, offset_in_bytes, 'bof'); 
     s=fread(fid, npoints_to_load,'ushort');
     image=reshape(s,nrows,[]);
     [outputs]=foo(image)
end

できる限り関数を最適化しましたfoo(可能な場合はコードをベクトル化し、適切なデータ クラスを使用するなど)。まだ行っていない唯一のことは、mex バージョンを作成することです。これを使おうと思ったparforのですが、うまくいきませんでした。各画像は独立していますが、上記のコードはデータをシリアルに読み取るため、実際には並列化できません。オプションがこのコードとデータベースにアクセスできるようにするにはどうすればよいparforですか? ありがとう

4

2 に答える 2

0

FREADこのループを効果的に並列実行するには、部分と部分の両方を並列に実行できる必要がありますfoo。をMATLABのようなものへのダミー呼び出しにfoo置き換えることで、その部分が並行して実行されることを確認できます。FREADRAND

matlabpoolワーカーはシングルスレッドモードで実行されることに注意してください。これは、すべてのワーカーを1台のマシンで実行している場合に特に重要です。fooMATLABの固有のマルチスレッドをうまく利用できた場合は、PARFOR代わりにループを使用すると、処理が遅くなる可能性があります。

大きな画像ファイルが1つしかない場合は、ファイルシステムで完全に並列アクセスできる場合とできない場合があります。これを回避する最善の方法はわかりません。ほぼ確実に、特定のファイルシステムに依存しています。

于 2013-02-26T10:46:35.950 に答える
0

ここでは、画像はすべて同じサイズ、または事前にわかっているサイズであると想定しています。つまり、現在の画像のサイズを知るために、以前のすべての画像をスキャンする必要はありません。これが当てはまらない場合、以下は役に立ちません。

複数のワーカーが 1 つのファイル ハンドルを共有しようとしているため、提供されたコードは parfor では機能しません。Matlab の並列ツールは、複数のコンピューター クラスターで使用するように設計されているため、ファイル ハンドルなどはうまく複製されません。

コードを parfor で機能させるには、次のように、ループ内でファイルを開いたり閉じたりする必要があります。

parfor image_number=1:N
  fid = fopen(filename, 'r');
  offset_in_bytes = npoints_per_image*element_size*(image_number-1);
  fseek(fid, offset_in_bytes, 'bof'); 
  s=fread(fid, npoints_to_load,'ushort');
  image=reshape(s,nrows,[]);
  [outputs]=foo(image);
  fclose(fid);
end

これによりプロセスにオーバーヘッドが追加されることがわかった場合は、ネストされたループと、場合によってはバッファリングを使用することをお勧めします。

chunk_size = ceil(N/10);
parfor i = 0:9
  fid = fopen(filename, 'r');

  %some buffering code here

  %start this iteration of the parfor loop at this image_number
  start_num = 1+(i * chunk_size); 
  end_num = min(N, (i+1) * chunk_size); %and end it at this one

  for image_number=start_num:end_num
    %your code here
  end

  fclose(fid);
end

Edric が述べたように、foo 関数でベクトル処理を十分に活用している場合、parfor によって matlab がシングル スレッド モードで実行されるため、あまり高速化されない可能性があります。

于 2013-03-27T18:19:03.423 に答える