技術

CUDAにおける線形メモリ(linear memory)とArray(CUarray)の違い

この記事は普段にも増して思い込みで書いてる度合いが高めなので注意が必要です。間違いがあれば指摘していただけるとありがたいです。

どちらもGPUのデバイスメモリ(グローバルメモリ)上に確保され、どちらもテクスチャリファレンス(サンプラ)を通して読み取り専用でアクセス出来る。
その際どちらの場合もテクスチャキャッシュが効く。
そういう意味では同じようなもの、と言えるが細かい違いが結構ある。

概念

線形メモリは汎用的に使えるメモリ領域のためのもの。CPUプログラミングで言うところのヒープメモリに相当し、用途は自由。
カーネルから自由に直接読み書き可能だが、テクスチャリファレンスを通して読み込む事もできる。

Arrayはテクスチャフェッチに最適化されたメモリ領域のためのもの。
テクスチャリファレンスやサーフェースリファレンスを通さないとカーネルからアクセスすることは出来ない。

使い方

生成方法

どちらもホストコード側でそれ用のAPIを使うことで生成する。
cuMemAllocなどで線形メモリを、cuArrayCreateなどでArrayを生成する。

ホストからのデータの読み書き

どちらもcuMemcpy系関数で行う。

カーネルにおける使い方

どちらもテクスチャリファレンスを通して同じようにして使える。
ただし、線形メモリはカーネルの引数に渡してカーネルから直接自由に読み書きすることも出来る。(というか多分これが線形メモリの本来の使い方。)

制限

基本的にArrayの方が制限がキツイ。
Arrayのひとつの要素(テクセル)はunsigned int8やfloatなどの決まった型 x 1 or 2 or 4個で構成されなければいけない。
線形メモリの場合はそういう制限はない。
ただし線形メモリでもテクスチャリファレンスを通して読む場合はArrayと同じ単位でしか読み込めない。
どちらの場合もカーネルで読み込んだテクセルをどう扱うかは自由であり、複数テクセルから独自の構造体を再構築したり出来るので、テクスチャリファレンスを通したとしても自由に独自の構造体を使えると言える。

テクスチャとして使う場合の解像度

例えばCompute Capability(以下CC)2.0以上の場合、1Dテクスチャの制限として、線形メモリなら長さ最大134217728(約1億3千万)だが、Arrayは65536までとなる。
ただし2DになるとCC2.0以上の場合微妙に逆転する。
という風にテクスチャとして使う場合の解像度の制限に差がある。

用途の制限

CC 2.0から追加されたサーフェースリファレンス(ざっくり言えば書き込みも可能なテクスチャリファレンス)のバックエンドとしてはArrayのみが対応している。
まぁ、線形メモリは普通に読み書き出来るのでそもそもそういった対応は必要ない。

速度

線形メモリはカーネルから直接読み書き可能だが、テクスチャリファレンスを通すことでテクスチャキャッシュが有効になり読み込みが高速化される。
(以前は線形メモリの直接アクセスにキャッシュは効かなかったが、最近はキャッシュが効くらしいので、テクスチャリファレンスを使うか否かで以前ほどの速度の差はないかもしれない。)
Arrayはそもそもテクスチャデータを表現するためのものなので、テクスチャリファレンスのバックエンドとして線形メモリを使う場合よりさらに高速にアクセスできる可能性がある。

まとめ

線形メモリとArrayのどっちが良いか。
当然Arrayにしか出来ないことをやるときにはArrayを選ばなければならないし、その逆もしかり。

問題はどっちでもいい場合にどっちを選ぶか。
スピードを求める場合はArrayを、それ以外の場合、特にとりあえず動くものを作るとかで設計がきっちり固まってない場合や、アルゴリズムがテクセル単位のデータアクセスにマッチしない場合は線形メモリでいいんじゃないかと思う。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です



※画像をクリックして別の画像を表示

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください