基本的にバイナリファイルからベクトルを読み書きするC++クラスがあります。単一のベクトルをメモリにロードする読み取り関数の例は、次のようになります。
int load (const __int64 index, T* values) const {
int re = _fseeki64(_file, index * _vectorSize + _offsetData, SEEK_SET);
assert(re == 0);
size_t read = fread(values, sizeof(T), _vectorElements, _file);
assert(read == _vectorElements);
return 0;}
OutプログラムはOpenMPでマルチスレッド化されており、複数のスレッドが同時に同じファイルにアクセスします。複数のスレッドによる問題を回避するために、OpenMPの重要なステートメント内で関数呼び出しを常にカバーしています。
#pragma omp critical {
load(...);
}
Microsoft Visual C ++ランタイムには、、などのいくつかの関数が含まれていることを知っています...たとえば、関数は次のように記述されます_fseek_nolock
。_fread_nolock
_fwrite_nolock
_fread_nolock()
この関数は、freadの非ロックバージョンです。他のスレッドによる干渉から保護されていないことを除いて、freadと同じです。他のスレッドをロックアウトするオーバーヘッドが発生しないため、より高速になる可能性があります。この関数は、シングルスレッドアプリケーションなどのスレッドセーフなコンテキストで、または呼び出し元のスコープがすでにスレッドの分離を処理している場合にのみ使用してください。
今私の質問:関数が「再入可能」呼び出しをブロックすることを理解しているので、他のスレッドが戻る前に他のスレッドが関数に入ることがありません。しかし、なぜそのように単一の機能を保護する必要があるのか理解できません。IMHO(_file
コードサンプル内の)ファイルポインタにアクセス/変更するすべての関数は保護する必要があるため、スレッドセーフにする必要があります。これには、実際に標準のC関数fseekとfreadを呼び出す関数ブロック全体の周りにロックを構築する必要があるため、このような非ブロッキング関数を提供する意味がわかりません。
私たちのパラノイドロックスキームはパフォーマンスをいくらか浪費すると思うので、誰かが私にこれらのロックメカニズムを説明できますか?
前もって感謝します!