OpenCLコアの䞊列ノむズおよび乱数関数

この蚘事に付属するノむズサンプルコヌドには、3次元グラフィックス甚の倧理石や雲などの自然なテクスチャを生成するのに圹立぀Perlinノむズ生成アルゎリズムの実装が含たれおいたす。 この蚘事には、Perlinノむズアルゎリズムを䜿甚しおクラりドむメヌゞを䜜成するテストが含たれおいたす。 Perlinのノむズアルゎリズムの詳现に぀いおは、「参照」を参照しおください。アルゎリズムの2次元および3次元バヌゞョンが含たれおいたす。 これは、関数が2぀たたは3぀のデヌタセットを入力ずしお受け取り、Perlinノむズの1぀の出力倀を䜜成するこずを意味したす。
ノむズの䟋には、擬䌌乱数ゞェネレヌタヌRNGの機胜も含たれおいたす。これは、結果の画像を実際にランダムに芋えるようにするのに十分な比范的良い結果を生成したす。 1次元、2次元、および3次元のバヌゞョンが含たれたす。この堎合の枬定数は、入力デヌタのセットの数に等しく、これに基づいお1぀の擬䌌ランダム出力倀が圢成されたす。

玹介ず動機


倚くのアプリケヌションでは、ある皋床の「ランダム性」、たたはより正確には「疑䌌ランダム性」が必芁です。 私たちは、arbitrary意的で䞍安定な、぀たり人にずっお「ノむズ」に芋える䞀連の意味に぀いお話しおいたす。 さらに、再珟性の目的で、アプリケヌションは、同じ入力倀たたは倀のセットを受け取ったずきに十分な信頌性でたったく同じシヌケンスを生成できる乱数ゞェネレヌタヌを必芁ずするこずがよくありたす。

ほずんどの乱数生成アルゎリズムでは、各生成倀が前の生成倀に䟝存し、シヌケンスの最初の生成倀が入力倀から盎接導出されるずいう事実により、この芁件が満たされたす。 乱数ゞェネレヌタヌぞのこのアプロヌチは、OpenCLなどの高レベルの䞊列コンピュヌティングを備えた蚀語では困難です。 倚数の蚈算スレッドのそれぞれに乱数の1぀の順次゜ヌスを埅機させるず、䞊列凊理ず䞊列凊理に基づくアルゎリズムのすべおの利点がれロになりたす。

この問題を解決する1぀の方法は、事前にランダムな倀の倧きなテヌブルを蚈算するこずです。 その埌、各䞊列スレッドはこのテヌブルに䞀意であるが厳密に定矩されたむンデックスを䜜成したす。 たずえば、画像を凊理するOpenCLカヌネルは、カヌネルによっお凊理たたは䜜成されおいるピクセルの座暙に基づいおむンデックスを蚈算するこずにより、事前䜜成されたテヌブルから゚ントリを遞択できたす。

このアプロヌチの欠点は、䞊列アルゎリズムを開始する前に乱数を䜜成する長い順次プロセスが必芁になるこずです。これにより、䞊列化䞭のパフォヌマンスの向䞊が制限されたす。 たたこの堎合、事前に䞊列アルゎリズムを開始する前に必芁な乱数の数を少なくずもおよそ知る必芁がありたす。 これは、各スレッドが䜿甚するランダム倀の数を動的に決定する必芁がある䞊列アルゎリズムにずっおは困難です。

NoiseサンプルコヌドのOpenCLカヌネルレベル関数は、䜜業をOpenCLで䜿甚される䞊列操䜜に分割するアルゎリズムにより適したアプロヌチを採甚しおいたす。

OpenCLのノむズず乱数を䜜成する


OpenCLでは、グロヌバルワヌクスペヌス䜜業項目の配列は、1、2、たたは3次元を䜿甚しお定矩されたす。 このグロヌバルスペヌスの各䜜業項目には、グロヌバルスペヌスのX、Y、Z軞に沿った座暙に察応する敎数倀を識別する䞀意のセットがありたす。

ノむズの䟋のPerlinノむズ関数ず乱数ゞェネレヌタヌは、最倧3぀の入力倀に基づいお乱数ノむズを䜜成したす。これは各䜜業項目のグロヌバル識別子になりたす。 別のアルゎリズムがありたす。グロヌバル識別子ず、カヌネルが受信たたは䜜成したデヌタ倀を組み合わせるこずで、1぀以䞊の倀を䜜成できたす。

たずえば、次のOpenCLカヌネルコヌドスニペットは、2次元のグロヌバルな䜜業項目識別子に基づいた乱数の䜜成を瀺しおいたす。

kernel void genRand() { uint x = get_global_id(0); uint y = get_global_id(1); uint rand_num = ParallelRNG2( x, y ); ... 

図1.乱数の䜿甚䟋2次元

このアプロヌチにより、ワヌクアむテム間で乱数ゞェネレヌタヌたたはノむズの機胜を䞊行しお実行できたすが、同時に、ワヌクアむテム間および同じワヌクアむテム内の他の倀間でランダムに倉化する倀の反埩可胜なシヌケンスで結果を取埗できたす。 耇数の2次元の倀セットを䜜成する必芁がある堎合は、3次元の䜜成関数を䜿甚できたす最初の2぀の入力倀はワヌクアむテムのグロヌバル識別子から取埗され、3番目の次元は必芁な远加の倀ごずに初期倀を連続的に増加させるこずによっお取埗されたす。 このアルゎリズムは、Perlinノむズを䜿甚した次の䟋のように、3次元ランダム倀たたはノむズ倀のいく぀かのセットで機胜するように拡匵できたす。

 kernel void multi2dNoise( float fScale, float offset ) { float fX = fScale * get_global_id(0); float fY = fScale * get_global_id(1); float fZ = offset; float randResult = Noise_3d( fX, fY, fZ ); ... 

図2. Perlinのノむズアルゎリズムの䜿甚䟋3次元

制限事項


Noise_2dおよびNoise_3d関数は同じ基本的なPerlinノむズアルゎリズムを䜿甚したすが、Perlinの掚奚事項に基づいお実装が異なりたす。 参照リストの最初のリンクを参照しおください。Noiseサンプルでは、​​noiseサンプルではNoise_3dのみが䜿甚され、Noise_2dテストカヌネルは、このサンプルを倉曎しお詊しおみたい読者のためにNoise.clファむルに含たれおいたす。

Noise_2dおよびNoise_3d関数は、入力浮動小数点倀で呌び出す必芁がありたす。 ランダムな倀の「テヌブル」図3を参照のサむズを指定するには、倀は0.0、128.0など䜕らかの範囲をカバヌする必芁がありたす。 読者は、クラりドの䟋を芋お、Perlinのノむズをさたざたな「自然に芋える」画像に倉換する方法を確認しおください。

ランダムテストで䜿甚されるデフォルトのParallelRNG関数は、ランダムなおよび同様の結果を提䟛したすが、最速の乱数生成アルゎリズムではありたせん。 この関数は、元は乱数ゞェネレヌタヌずしお䜿甚するこずを意図しおいない「りォンハッシュ」に基づいおいたす。 それにもかかわらず、乱数ゞェネレヌタヌのいく぀かの䞀般的な機胜Noise.clファむル内のコメントアりトされた䟋は、特に結果の䞋䜍ビットのビットで2次元画像を埋めるずきに目に芋える再珟性を瀺したした。 読者は、乱数ゞェネレヌタヌの他のより高速な関数を詊すこずもできたす。

デフォルトのParallelRNG関数は、結果ずしお32ビットの笊号なし敎数のみを生成したす。 0.0、1.0などの範囲で浮動小数点倀が必芁な堎合、アプリケヌションはこの範囲のマッピングを適甚する必芁がありたす。 ランダムパタヌンは、ランダムな笊号なし敎数の結果ず範囲0、255を照合しお、グレヌスケヌルピクセル倀を䜜成したす。 これを行うには、バむナリAND挔算を適甚しお8ビットを遞択したす。

デフォルトのParallelRNG関数は、前に䜜成された倀に基づいお、連続した呌び出しに察しお4,294,967,296 2,232 すべおの笊号なし敎数倀を生成したせん。 個々の初期倀ごずに、疑䌌ランダムシヌケンスサむクルの倀は、合蚈7000の䞀意の倀から玄20億の倀たでの範囲になりたす。 ParallelRNG関数は、玄20の異なるサむクルを䜜成したす。 著者は、OpenCLカヌネルのどの䜜業芁玠も、最小のルヌプで圢成されるよりも倚くの乱数を連続しお生成する必芁があるずは考えおいたせん。

この関数の2次元および3次元バヌゞョンParallelRNG2およびParallelRNG3は、前のParallelRNG呌び出しの結果ずサむクル長を倉曎する次の入力倀の間にバむナリXOR挔算を適甚するこずにより、ルヌプミキシングを䜿甚したす。 それでも、このような倉曎された動䜜は詳现な分析の察象ではなかったため、ParallelRNG関数がアプリケヌションのニヌズを満たしおいるこずを泚意深く確認するこずをお勧めしたす。

プロゞェクト構造


このセクションでは、サンプルアプリケヌションの゜ヌスコヌドの基本芁玠のみをリストしたす。

NoiseMain.cpp


メむン

メむン入力機胜。 コマンドラむンパラメヌタヌを解析した埌、OpenCLを初期化し、Noise.clファむルからOpenCLプログラムをコンパむルし、カヌネルの1぀を起動甚に準備し、 ExecuteNoiseKernelを呌び出しおからExecuteNoiseReferenceを呌び出したす。 これらの2぀の実装が同じ結果を䞎えるこずを確認した埌、 mainはこれらの各機胜の動䜜時間に関する情報を提䟛し、それらの䜜業から生じる画像を保存したす。

ExecuteNoiseKernel

OpenCLで遞択したノむズカヌネルを構成しお実行したす。

ExecuteNoiseReference

遞択したノむズC参照コヌドを構成しお実行したす。

Noise.cl


defaut_perm [256]

3次元のパヌリンノむズのコアのランダム倀0〜255の衚。 ランダム性をさらに高めるために、このテヌブルを生成し、Perlinノむズのコアに送信できたす。

grads2d [16]

16個の均䞀に分垃した単䜍ベクトル、2次元のパヌリンノむズのコアの募配。

grads3d [16]

3次元のパヌリンノむズのコアに察する16のベクトルグラデヌション。

ParallelRNG

擬䌌乱数ゞェネレヌタ、1぀の入力倀に察しお1぀のパス。 乱数ゞェネレヌタヌの代替機胜はコメント化されおいたすが、より速く機胜するが悪い結果をもたらす機胜を読者がテストしたい堎合に備えお、ファむルに远加されたす。

ParallelRNG2

2぀の入力倀に察しお2぀のパスを実行する乱数ゞェネレヌタヌ。

ParallelRNG3

3぀の入力倀に察しお3぀のパスを実行する乱数ゞェネレヌタヌ。

weight_poly3、weight_poly5およびWEIGHT

これらは、募配の連続性を確保するためにPerlinノむズアルゎリズムで䜿甚される代替の重み関数です。 2次優先関数は、2次導関数の連続性も保蚌したす。 WEIGHTマクロは、䜿甚する機胜を遞択したす。

NORM256

範囲0、255を-1.0、1.0に倉換するマクロ。

interp

OpenCLを䜿甚した双線圢補間。

hash_grad_dot2

募配を遞択し、Perlinノむズ関数Noise_2dの䞀郚ずしお入力XY倀を持぀スカラヌ積を蚈算したす。

Noise_2d

2぀の入力倀を持぀Perlinノむズゞェネレヌタヌ。

hash_grad_dot3

募配を遞択し、Perlinノむズ関数Noise_3dの䞀郚ずしお入力XYZ倀を持぀スカラヌ積を蚈算したす。

Noise_3d

3぀の入力倀を持぀Perlinノむズゞェネレヌタヌ。

クラりド

Noise_3dを䜿甚しおCloudTestの単䞀ピクセルの「クラりド」出力画像を䜜成したす。

map256

パヌリンノむズの出力範囲-1.0、1.0をグレヌスケヌルピクセルの生成に必芁な範囲0、255に倉換したす。

CloudTest

クラりドむメヌゞテスト。 スラむスパラメヌタヌはクラりド関数に枡されるため、システムコヌドは他のクラりドむメヌゞを䜜成できたす。

Noise2dTest

Noise_2dテストはデフォルトでは䜿甚されたせん。

Noise3dTest

Noise_3dのテスト-デフォルトでのパヌリンノむズ関数。 map256を䜿甚しお、グレヌスケヌル画像のピクセル倀を取埗したす。

RandomTest

ParallelRNG3テストは、笊号なし敎数結果の最䞋䜍バむトを䜿甚しお、グレヌスケヌルむメヌゞを生成したす。

Visual Studioバヌゞョン2012および2013甚に2぀のMicrosoft Visual Studio゜リュヌションファむルが提䟛されおいたす。これらはNoise_2012.slnずNoise_2013.slnです。 読者がVisual Studioの新しいバヌゞョンを䜿甚しおいる堎合、Visual Studioの゜リュヌションずプロゞェクトの曎新機胜を䜿甚しお、これらのファむルに基づいお新しい゜リュヌションを䜜成できたす。
どちらの゜リュヌションも、 むンテル®OpenCL™コヌドビルダヌがシステムにむンストヌルされおいるこずを前提ずしおいたす。

サンプル管理


このサンプルは、.exeファむルがあるフォルダヌのMicrosoft Windows *コマンドプロンプトから実行できたす。
Noise.exe <>


パラメヌタ


-h --help
コマンドラむンにヘルプを衚瀺したす。 デモンストレヌションはトリガヌされたせん。

-t --type [ all | cpu | gpu | acc | default | < OpenCL>
OpenCLカヌネルが実行されるデバむスのタむプを遞択したす。 デフォルト倀はallです。

CL_DEVICE_TYPE_ALL | CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU |
CL_DEVICE_TYPE_ACCELERATOR | CL_DEVICE_TYPE_DEFAULT
<OpenCLデバむスタむプ定数>

-p --platform < >
䜿甚するプラットフォヌムの遞択。 デモが開始されるず、すべおのプラットフォヌム番号ず名前のリストが衚瀺されたす。 [遞択枈み]は、䜿甚するプラットフォヌムの右偎に衚瀺されたす。 文字列を䜿甚する堎合、プラットフォヌム名を䞀意に認識するのに十分な文字を指定したす。 デフォルト倀はIntelです。

-d --device < >
OpenCLコアが実行されるデバむスを番号たたは名前で遞択したす。 デモンストレヌションが開始されるず、䜿甚されおいるプラ​​ットフォヌム䞊のすべおの番号ずデバむス名のリストが衚瀺されたす。 珟圚のデバむスの右偎に、[遞択枈み]が衚瀺されたす。 デフォルト倀は0です。

-r --run [ random | perlin | clouds ]
実行する機胜デモを遞択したす。 乱数ゞェネレヌタヌ、Perlinノむズアルゎリズム、およびクラりドむメヌゞゞェネレヌタヌにはデモカヌネルがありたす。 デフォルト倀はランダムです。

-s --seed < >
アルゎリズムの結果が倉化する敎数入力倀。 デフォルト倀は1です。

Noise.exeは、OpenCLコアの実行時間ず同等の参照Cコヌド、および䞡方のアルゎリズムの出力ファむルの名前を衚瀺したす。 情報の出力が完了するず、プログラムはナヌザヌが終了する前にEnterキヌを抌すこずを期埅したす。 C参照コヌドの機胜は最適化されおいないこずに泚意しおください;それらの目的は、OpenCLカヌネルコヌドの正確さを怜蚌するこずだけです。

結果分析


Noise.exeが完了したら、䜜業フォルダヌのBMPむメヌゞファむルOutputOpenCL.bmpずOutputReference.bmpを参照しお、OpenCLずC ++コヌドの結果を比范したす。 2぀の画像は同じである必芁がありたすが、Perlinノむズの2぀の画像間たたは雲の2぀の画像間にはわずかな違いがある堎合がありたす。
ノむズアルゎリズムの結果Perlinノむズは図3のようになりたす。


図3. Perlinノむズアルゎリズムの結果

ランダムアルゎリズム乱数ゞェネレヌタヌの結果は、図4のようになりたす。


図4.乱数ゞェネレヌタヌの結果

クラりドアルゎリズムの結果は、図5のようになりたす。


図5.クラりド䜜成アルゎリズムの結果

参照資料


  1. C.パヌリン、K。「ノむズ改善」
  2. 「4バむト敎数のハッシュ」
  3. M.オヌバヌトンMA、「高速高品質䞊列乱数ゞェネレヌタヌ」、Dr。Webサむト ドブス2011
  4. むンテル®デゞタル乱数ゞェネレヌタヌDRNGラむブラリの実装ず䜿甚
  5. むンテル゜フトりェアラむセンスのサンプルラむセンス契玄
  6. むンテル®OpenCL™コヌドビルダヌ

Source: https://habr.com/ru/post/J279393/


All Articles