画像ファイルの読み取りと画像の各ピクセルの読み取りを一度だけ行うCプログラムを作成しています。したがって、fread() を使用して一度ファイルを読み取り、それをいくつかの動的変数 (ヒープ変数) に格納するか、各ピクセルに対して頻繁に fread() を使用する必要がありますか?? 画像のサイズは 1000*1000 ~ 5000*5000 です。MPI と CUDA で同じプログラムを拡張します。他の提案をいただければ幸いです。ありがとうございました。
8 に答える
12ビットカラーのARGB画像でさえ、5,000 *5,000ピクセルの解像度で約150MBを必要とします。これは、現在のすべてのPCや多くのGPUカードの機能の範囲内です。そのような種類のメモリを使用できる場合は、動的に割り当てられた配列、またはそれらの線に沿ったもので1回読み取る必要があります。img[1234][4321][RED] = 34
これにより、I / O関数でコードを複雑にするのではなく、画像全体を大きなI / Oブロックで読み取ることができ、より高速になり、ダイレクトメモリ操作()を使用できます。
そのような種類のメモリが利用できない場合はmmap()
、OSがファイルを仮想メモリにマップするために、またはそれに相当するものが存在するかどうかを確認してください。計算コストは高くなりますが、必ずしもすべてをメモリにロードしなくても、ダイレクトメモリ操作を使用できるという利点があります。
とは言うものの、最新のOSはデータの大規模なキャッシュとプリフェッチを実行するため、使用fread()
はそれほど遅くない可能性があります。さらに、glibc-2.3以降を搭載した現在のLinuxシステムでは、アプリケーションが標準機能mmap()
でI / Oを実行する場合でも、オプションでファイルアクセスに使用できます。stdio
決定を下すのに役立つ可能性のある別の質問があります。fopen()、fclose()はどの程度正確に機能しますか?
速度を求めている場合は、ファイル全体を一度にメモリにロードして、そこで操作するのが最適です。これにより、データを提供するためにハードディスクドライバを不必要に呼び出すことを回避できます。5kイメージに25,000,000の異なる4バイトチャンク(32ビットRGBAを想定)を提供することについて話し始めると、潜在的に多くのシーク、読み取り、および待機を検討していることになります。
これは、古典的なメモリと速度のトレードオフの1つです。顧客に十分なメモリがある場合は、すべてのデータをメモリにロードしてから、変換を実行するのが最適です。
それ以外の場合は、一度に十分なデータをロードして(ページング)、ターゲットのメモリプロファイルに高速で適合するようにしてください。
一般に、ファイルを処理する最も簡単な方法は、1 回の大きな I/O ですべてをメモリに読み込み、それ以降はメモリから処理することです。多くの場合、コードも単純になります。
もちろん、使用可能な連続したメモリ チャンクに収まらない可能性のあるファイルについて心配する必要があります。それを (保釈するのではなく) 適切に処理すると、コードははるかに複雑になります。認定された怠惰なプログラマーとして、私はそれをやり遂げることができれば、ただ保釈することを好みます。:-)
処理する必要があるアルゴリズムの種類によって異なります。5000 * 5000 の画像は約 95 Mb です。大したことではありません。
GPU 側では、約 4MB ~ 16MB のブロックで GPU メモリに非同期アップロードして、帯域幅を飽和させることができます。
#pseudocode:
for chunk in fread(4096MB):
gpu.uploadAsync (chunk) # will not block
gpu.execute() #wait that all the previous memory transfers are completed.
cudaでPinned Memoryを使用する必要があります。ファイルコピーをメモリマップすると、ブロックはさらに高速になると思います。
いつものように、最適なチューニングのためにアプリケーションをプロファイリングします。
場合によります。ソフトウェアを実行するほとんどのコンピュータのメモリ量を試して見積もる必要があります。また、コードの速度がどれほど重要かにも依存します。
明らかに、一方のアプローチはより高速ですが、もう一方のアプローチはより多くのメモリを使用します。一般に、最近のほとんどのコンピューターのメモリにロードしても問題なく、そのほうが簡単です。ただし、特定のケースの長所と短所を比較検討する必要があります。
コメントとして書こうと思ったのですが、長くなってしまいました。しかし、ポイントに...
私はTEDとジョナサン・ウッドに同意します:
一般に、ファイルを処理する最も簡単な方法は、1 回の大きな I/O ですべてをメモリに読み込み、それ以降はメモリから処理することです。多くの場合、コードも単純になります。
-TED
場合によります。ソフトウェアを実行するほとんどのコンピュータのメモリ量を試して見積もる必要があります。また、コードの速度がどれほど重要かにも依存します。
明らかに、一方のアプローチは高速ですが、もう一方のアプローチはより多くのメモリを使用します。一般に、最近のほとんどのコンピューターのメモリにロードしても問題なく、そのほうが簡単です。ただし、特定のケースでの長所と短所を比較検討する必要があります
-ジョナサン・ウッド
32 ビット カラーの 5000*5000 ピクセルは、およそ 100 メガバイトのメモリを消費することに注意してください (+ 多少のオーバーヘッドや、ソフトウェアが必要とするものは何でも)。ほとんどの最新のデスクトップ コンピューターには、少なくとも 1 ~ 2 ギガバイトのメモリが搭載されていると思います (私の場合は 2008 年に購入し、4 を搭載しています)。すぐに、ラップトップのメモリが少なくなる可能性があります。
CUDA の側面も興味深いです (CUDA についてはほとんど知りません)。データは GPU のメモリにロードされますか? CUDA 対応 GPU の通常のメモリ容量はどれくらいですか? PCI-e バスがボトルネックになる可能性はありますか (おそらくない..?)? CUDA をサポートする一般的なCUDA 対応のデスクトップおよびラップトップ GPUのメモリ量を調べます。
ある種の妥協は、読み取りをバッファリングしようとしている可能性があり、別のスレッドがファイルからデータを「先読み」し、他のスレッドがデータを処理 (およびメモリを解放) することです。
Windows で mmap() linux または mapviewoffile() を使用することを検討してください。
メモリに保存すると、間違いなく高速になります。毎回ハード ドライブから小さなチャンクを読み取ると、最小アクセス時間などのために常に遅延が発生します。