マルチスレッディング
GDAL API: re-entrant, but (generally) not thread-safe
用語 スレッドセーフ
または 再入可能
の正確な意味は完全に標準化されていません.ここでは, QTの定義 を使用します. 特に, C関数またはC++メソッドは, 複数のスレッドから同時に呼び出すことができると言われます. しかし 各呼び出しが独自のデータを使用する場合のみ, 再入可能であるとされます.
すべてのGDAL公開C関数とC++メソッドは再入可能ですが, 以下の例外があります:
GDALAllRegister()
のような一般的な初期化関数.GDALDestroy()
やOSRCleanup()
のような一般的なクリーンアップ関数.
これらの関数は複数のスレッドから同時に呼び出すべきではありません.また, プログラムの初期化と終了時には, 一般的にこれらの関数をプログラムのメインスレッドから呼び出すのがベストプラクティスです.
特に指定されていない限り, GDAL公開C関数とC++メソッドはスレッドセーフであると仮定してはいけません. つまり, 同じデータインスタンスに対して複数のスレッドから同時にGDAL関数を呼び出すべきではありません. また, 所有関係を通じて密接に関連しているインスタンスに対しても同様です. たとえば, マルチバンドラスターデータセットの場合,同じ GDALDataset
インスタンスによって所有されている異なる GDALRasterBand
インスタンスに対して同時にGDAL関数を呼び出すことは安全ではありません (各スレッドは代わりに異なるGDALDatasetを操作するべきです). 同様に, 複数の OGRLayer
を所有するGDALDatasetの場合も同様です.
その理由は, GDALDatasetやGDALRasterBandのほとんどの実装が状態を持っているためです.GDALDatasetは通常, ファイルハンドルを所有し, それに対してシーク/読み取り操作を行うため,同時アクセスを許可しません. 特定のGDALDatasetに関連するブロックキャッシュ関連の構造はスレッドセーフではありません. ドライバは, さまざまなメタデータにアクセスするための遅延初期化戦略を実装することがよくあり, これらのメタデータにアクセスするためのメソッドが初めて呼び出されたときにのみ解決されます. ドライバはまた, スレッドセーフでないオブジェクトを公開するサードパーティライブラリに依存することがあります.
これらの制限は, CおよびC++のABI, およびすべての言語バインディングに適用されます(特別な注意を払って呼び出しを直列化する場合を除く)
Thread-safe GDAL dataset instances for raster read-only use cases
Added in version 3.10.
RFC 101 adds a new capability to open, or obtain, a thread-safe dataset from any dataset, but only for raster read-only use cases.
At open time, this can be done by passing GDAL_OF_RASTER | GDAL_OF_THREAD_SAFE
to GDALOpenEx()
/ GDALDataset::Open()
.
Given an existing GDALDataset* instance, GDALDataset::IsThreadSafe()
can be used to determine if it is thread-safe or not. If not,
GDALDataset::GetThreadSafeDataset()
can be used.
Note that the generic implementation of this capability involves opening one dataset the first time a thread-safe dataset/raster band is accessed by a thread. While this is an implementation detail that can be ignored to develop code, it is important to note regarding potential performance impacts
GDALブロックキャッシュとマルチスレッディング
現在のGDALラスターブロックキャッシュの設計では, 複数のデータセットの同時読み取りが許可されています. ただし, 複数のスレッドから複数のデータセットに書き込む場合, ブロックキャッシュメカニズムのグローバル構造体でのロック競合によるパフォーマンス問題が発生する可能性があります.
RAMの断片化とマルチスレッディング
ラスターデータセットの読み取りまたは書き込みを行うマルチスレッディングを含むシナリオは,Linuxのデフォルトの動的メモリアロケータを使用している場合, 高いRAM使用量を引き起こす傾向があることが観察されています. 代替の tcmalloc メモリアロケータを使用すると, 使用される仮想メモリと常駐メモリの量を減らすのに役立ちます.
たとえば, Debian/Ubuntuディストリビューションでは, libtcmalloc-minimal4
パッケージをインストールし, GDALを実行するバイナリを次のように実行することで, これを行うことができます:
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4 ./binary
GDALとマルチプロセッシング
GDAL操作の途中でPOSIX fork() APIを呼び出すべきではありません. そうしないと, フォークされたプロセスでミューテックスなどの構造体が永遠にロックされたように見える可能性があります. マルチプロセッシングを行う場合, GDAL操作を行う前にプロセスをフォークすることをお勧めします. 複数のサブプロセスで同じGDALDatasetインスタンスに操作を行うと, 基になるファイルディスクリプタが共有されているため, 一般的に誤った結果になります.