AMD APP SDK抜象化レむダヌの蚈算CAL

AMD APP 前半では、AMD Intermediate LanguageILテクノロゞヌに぀いお説明したした。 タむトルから掚枬できるように、この蚘事では2番目のコンポヌネントであるAMD Compute Abstraction LayerCALに぀いお説明したす。 これらの2぀のテクノロゞヌは互いに切り離せたせん。䞀方を䜿甚せずに他方を䜿甚するこずは䞍可胜です。 したがっお、さらに理解するために、最初の郚分に慣れるこずをお勧めしたす。

AMD GPUを䜿甚しおトップレベルで䜜業する際の䞻な偎面を匷調し、このテクノロゞヌの限界ず、䜿甚する際に起こりうる問題に぀いお説明したす。 猫の䞋で誰が気にしおください。

導入する代わりに


私がAMD GPUのプログラミングを理解し始めたずき、圌らは私がこれに䜕を䜿うのか尋ねおきたした。 「ATI CAL 」ず答えた。 「はい、ATIは本圓にCALです 」ず私は答えたした。
䞀般に、略語CALの発音はわかりたせんが、人を困らせないように「O」で発音したす。

簡朔にするために、最初の郚分でカヌネルによっお蚘述されたプログラムを瀺したす 。 カヌネルずは、プログラムの゜ヌスコヌドず、GPUにロヌドされたコンパむル枈みのバむナリコヌドの䞡方を意味したす。 AMD CALを介しおGPUで動䜜するプログラムの党文は提䟛したせんが、䞻な䜜業点に぀いお説明したす。

開始するには、AMD APP SDKの2぀のヘッダヌファむルが必芁です。

ご芧のずおり、ランタむムAPIずドラむバヌAPIを備えたNvidia CUDAずは異なり、AMDではドラむバヌAPIのみが䜿甚可胜です。 したがっお、アプリケヌションの操䜜のために、適切なラむブラリぞのリンクを忘れないでください。

ほずんどの関数呌び出しは、CALresult型の倀を返したす。 合蚈11の戻りコヌドが䜿甚可胜です。 私たちにずっお最も重芁なのは、CAL_RESULT_OKずいうコヌドで、0に等しい呌び出しが正垞に完了したこずを瀺したす。

行きたしょう。

ドラむバヌの初期化


ルヌル番号1 GPUでの䜜業を開始する前に、次の呌び出しで手を掗っおドラむバヌを初期化したす。
CALresult result = calInit(); 

ルヌル番号2 GPUで䜜業した埌、ゞョブを正しく完了するために自分ですすぐこずを忘れないでください。 これは、次の呌び出しによっお行われたす。
 CALresult result = calShutdown(); 

これらの2぀の呌び出しは垞にペアにする必芁がありたす。 プログラムにはそれらのいく぀かそのような呌び出しのペアが存圚する可胜性がありたすが、これらの呌び出し以倖でGPUを䜿甚しないでください。この動䜜はハヌドりェア䟋倖を䌎う堎合がありたす 。

GPU情報の取埗


サポヌトされおいる GPUの数を確認したすシステム内のAMD GPUの総数よりも少ない堎合がありたす。
 unsigned int deviceCount = 0; CALresult result = calDeviceGetCount( &deviceCount ); 

この蚘事では、GPU識別子の䜿甚堎所を瀺したすが、識別子0の䞋でGPUを「䜿甚」したす。䞀般に、この識別子は0からdeviceCount-1たでの倀を取りたす。

GPUに関する情報をご芧ください。
 unsigned int deviceId = 0; //  GPU CALdeviceinfo deviceInfo; CALresult result = calDeviceGetInfo( &deviceInfo, deviceId ); CALdeviceattribs deviceAttribs; deviceAttribs.struct_size = sizeof( deviceAttribs ); CALresult result = calDeviceGetAttribs( &deviceAttribs, deviceId ); 

CALdeviceinfo構造で最も重芁なこずは、GPUチップ識別子です。 ここでは、デバむスカヌネルISAず呌びたす 。
 typedef struct CALdeviceinfoRec { CALtarget target; /**< Device Kernel ISA */ CALuint maxResource1DWidth; /**< Maximum resource 1D width */ CALuint maxResource2DWidth; /**< Maximum resource 2D width */ CALuint maxResource2DHeight; /**< Maximum resource 2D height */ } CALdeviceinfo; 

構造䜓の残りのフィヌルドは、このGPUに割り圓おるこずができる2぀の座暙でのテクスチャメモリの最倧サむズを決定したす。

GPU属性を担圓するCALdeviceattribs構造は、はるかに興味深いものです構造䜓フィヌルドをいく぀か玹介したす。
 typedef struct CALdeviceattribsRec { CALtarget target; /**< Asic identifier (  Device Kernel ISA) */ CALuint localRAM; /**<   GPU RAM   */ CALuint wavefrontSize; /**<  warp'a (      ) */ CALuint numberOfSIMD; /**<   */ CALboolean computeShader; /**<   Compute Shader */ CALuint pitch_alignment; /**<        calCreateRes */ /*   */ } CALdeviceattribs; 

ルヌル番号3 CALdeviceattribs.pitch_alignmentフィヌルドは、バむトではなくメモリ芁玠で枬定されたす。 メモリ芁玠は、8、16、たたは32ビットレゞスタの1、2、たたは4コンポヌネントベクトルです。

そしお、CALdeviceinfo.targetフィヌルドCALdeviceattribs.targetが取りうる倀を詳しく芋おみたしょう
 /** Device Kernel ISA */ typedef enum CALtargetEnum { CAL_TARGET_600, /**< R600 GPU ISA */ CAL_TARGET_610, /**< RV610 GPU ISA */ CAL_TARGET_630, /**< RV630 GPU ISA */ CAL_TARGET_670, /**< RV670 GPU ISA */ CAL_TARGET_7XX, /**< R700 class GPU ISA */ CAL_TARGET_770, /**< RV770 GPU ISA */ CAL_TARGET_710, /**< RV710 GPU ISA */ CAL_TARGET_730, /**< RV730 GPU ISA */ CAL_TARGET_CYPRESS, /**< CYPRESS GPU ISA */ CAL_TARGET_JUNIPER, /**< JUNIPER GPU ISA */ CAL_TARGET_REDWOOD, /**< REDWOOD GPU ISA */ CAL_TARGET_CEDAR, /**< CEDAR GPU ISA */ CAL_TARGET_RESERVED0, CAL_TARGET_RESERVED1, CAL_TARGET_WRESTLER, /**< WRESTLER GPU ISA */ CAL_TARGET_CAYMAN, /**< CAYMAN GPU ISA */ CAL_TARGET_RESERVED2, CAL_TARGET_BARTS, /**< BARTS GPU ISA */ } CALtarget; 

このフィヌルドは、GPUが構築されおいるチップを瀺しおいるこずがわかりたす。 したがっお、AMD CALを䜿甚しお、GPUが䞖界で䜕ず呌ばれおいるのかRadeon HD 3850などを正確に芋぀けるこずは䞍可胜です。 ここにそのような䟿利な技術がありたす...しかし、䟋えば、Radeon HD 5750ずRadeon HD 6750は実際には同じビデオカヌドであるずいうこずを芳察するのは面癜かったです メモリ操䜜の頻床はわずかに異なりたす数パヌセント以内。

もう1぀泚意しおください。このリストにはEvergreen GPUがありたせん。これに぀いおは前半で説明したした。 私の掚枬では、EvergreenファミリGPUはサむプレスチップCAL_TARGET_CYPRESSから始たるず思われたす。 以前のものは、新しい機胜埪環シフト、操䜜フラグず64ビット操䜜のサポヌトをサポヌトしない前䞖代のみです。

さらに䜜業を進めるには、GPUずやり取りするデバむス蚘述子デバむスを䜜成する必芁がありたす。
 unsigned int deviceId = 0; //  GPU CALdevice device; CALresult result = calDeviceOpen( &device, deviceId ); CALcontext context; result = calCtxCreate( &context, device ); 

このGPUを䜿甚しおアプリケヌション内で動䜜するには、コンテキストが必芁です。 すべおのGPU䜜業は、このコンテキストを䜿甚しお行われたす。 コンテキストを削陀するずすぐに、割り圓おられたすべおのリ゜ヌスが解攟されたず芋なされ、GPU䞊のすべおの䞍完党なタスクが匷制的に完了したす。

デバむスでの䜜業を終えた埌、ペアの呌び出しを忘れないでください。
 calCtxDestroy( context ); calDeviceClose( device ); 

呌び出しはこの順序で実行する必芁がありたす。そうしないず、 ハヌドりェア䟋倖が発生したす。

それで、デバむスずそのコンテキストを䜜成したした。

メモリ割り圓お


メモリを操䜜するには、 リ゜ヌスを割り圓おる必芁がありたす。 ドキュメントによるず、リ゜ヌスはロヌカルメモリロヌカルメモリ=ストリヌムプロセッサメモリおよびリモヌトメモリリモヌトメモリ=システムメモリに配眮できたす。 私が理解しおいるように、リモヌトメモリはRAMに過ぎず、ロヌカルメモリはGPU自䜓のメモリです。

ロヌカルメモリがあるのにリモヌトメモリが必芁なのはなぜですか たず、耇数のGPU間で同じメモリを共有する必芁がありたす。 ぀たり、リモヌトメモリを䞀床割り圓おお、耇数のGPUから操䜜できたす。 第二に、すべおのGPUがメモリぞの盎接アクセスをサポヌトしおいるわけではありたせん以䞋の「メモリぞの盎接アクセスの取埗」を参照。

 CALresource resource; unsigned int memoryWidth; unsigned int memoryHight; CALformat memoryFormat; unsigned int flags; //      // 1D  CALresult result = calResAllocRemote1D( &resource, &device, 1, memoryWidth, memoryFormat, flags ); /*         GPU,    -     ,   -      (1   ) */ // 2D  CALresult result = calResAllocRemote2D( &resource, &device, 1, memoryWidth, memoryHeight, memoryFormat, flags ); //      // 1D  CALresult result = calResAllocLocal1D( &resource, device, memoryWidth, memoryFormat, flags ); /*  ,       ,       */ // 2D  CALresult result = calResAllocLocal2D( &resource, device, memoryWidth, memoryHeight, memoryFormat, flags ); 

割り圓おられたリ゜ヌスの幅ず高さは、メモリ芁玠で枬定されたす。
メモリヌ芁玠自䜓は、memoryFormatパラメヌタヌによっお蚘述されたす。
 //  ,         /** Data format representation */ typedef enum CALformatEnum { CAL_FORMAT_UNORM_INT8_1, /**< 1 component, normalized unsigned 8-bit integer value per component */ CAL_FORMAT_UNORM_INT8_4, /**< 4 component, normalized unsigned 8-bit integer value per component */ CAL_FORMAT_UNORM_INT32_1, /**< 1 component, normalized unsigned 32-bit integer value per component */ CAL_FORMAT_UNORM_INT32_4, /**< 4 component, normalized unsigned 32-bit integer value per component */ CAL_FORMAT_SNORM_INT8_1, /**< 1 component, normalized signed 8-bit integer value per component */ CAL_FORMAT_SNORM_INT8_4, /**< 4 component, normalized signed 8-bit integer value per component */ CAL_FORMAT_SNORM_INT32_1, /**< 1 component, normalized signed 32-bit integer value per component */ CAL_FORMAT_SNORM_INT32_4, /**< 4 component, normalized signed 32-bit integer value per component */ CAL_FORMAT_UNSIGNED_INT8_1, /**< 1 component, unnormalized unsigned 8-bit integer value per component */ CAL_FORMAT_UNSIGNED_INT8_4, /**< 4 component, unnormalized unsigned 8-bit integer value per component */ CAL_FORMAT_SIGNED_INT8_1, /**< 1 component, unnormalized signed 8-bit integer value per component */ CAL_FORMAT_SIGNED_INT8_4, /**< 4 component, unnormalized signed 8-bit integer value per component */ CAL_FORMAT_UNSIGNED_INT32_1, /**< 1 component, unnormalized unsigned 32-bit integer value per component */ CAL_FORMAT_UNSIGNED_INT32_4, /**< 4 component, unnormalized unsigned 32-bit integer value per component */ CAL_FORMAT_SIGNED_INT32_1, /**< 1 component, unnormalized signed 32-bit integer value per component */ CAL_FORMAT_SIGNED_INT32_4, /**< 4 component, unnormalized signed 32-bit integer value per component */ CAL_FORMAT_UNORM_SHORT_565, /**< 3 component, normalized 5-6-5 RGB image. */ CAL_FORMAT_UNORM_SHORT_555, /**< 4 component, normalized x-5-5-5 xRGB image */ CAL_FORMAT_UNORM_INT10_3, /**< 4 component, normalized x-10-10-10 xRGB */ CAL_FORMAT_FLOAT32_1, /**< A 1 component, 32-bit float value per component */ CAL_FORMAT_FLOAT32_4, /**< A 4 component, 32-bit float value per component */ CAL_FORMAT_FLOAT64_1, /**< A 1 component, 64-bit float value per component */ CAL_FORMAT_FLOAT64_2, /**< A 2 component, 64-bit float value per component */ } CALformat; 

叀いビデオカヌド゚バヌグリヌンではないでの64ビット操䜜がfloat型のデヌタでのみ実行できるのは残念です...

ルヌル番号4芁玠フォヌマットは、GPUがこの芁玠にあるデヌタを解釈する方法のみを説明したす。 物理的には、芁玠は垞に16バむトのメモリを占有したす。

これは、最初の郚分でリ゜ヌスを次のように説明したこずを思い出すず理解できたす。
 dcl_resource_id(0)_type(2d,unnorm)_fmtx(uint)_fmty(uint)_fmtz(uint)_fmtw(uint) 

たた、AMD IL蚀語仕様によるず、fmtx-fmtw倀が必芁です。 ぀たり、次のコヌドこのようなものは、1コンポヌネントベクトル型の芁玠を持぀テクスチャヌを蚘述できたすは正しくありたせん。
 dcl_resource_id(0)_type(2d,unnorm)_fmtx(uint) 

ルヌル番号5カヌネルで宣蚀するタむプを遵守し、リ゜ヌスを割り圓おるずき。 それらが䞀臎しない堎合、リ゜ヌスをカヌネルにバむンドできたせん。

ルヌル番号6定数メモリの堎合、芁玠タむプは垞にfloatタむプでなければなりたせん。

なぜこれが行われるのかは定かではありたせん。なぜなら、定数メモリから敎数倀をロヌドできるからですこの䟋ではこれを実行しおいたす。

メモリを割り圓おるずきに必芁なフラグに぀いお、もう少し説明したす。
 /** CAL resource allocation flags **/ typedef enum CALresallocflagsEnum { CAL_RESALLOC_GLOBAL_BUFFER = 1, /**< used for global import/export buffer */ CAL_RESALLOC_CACHEABLE = 2, /**< cacheable memory? */ } CALresallocflags; 

セカンドフラグを䜿甚したこずはありたせん。それが有利な堎合はわかりたせん。 そしお、著者自身のコメントにある疑問笊から刀断するず、圌らも知らない埮笑。
ただし、グロヌバルバッファを割り圓おるには最初のフラグが必芁です "g []"。

次に、理論を実際に適甚したす。 前の蚘事で説明した䟋を念頭に眮いお、カヌネルの起動パラメヌタヌも蚭定したす。
 unsigned int blocks = 4; //  4  unsigned int threads = 64; //  64    //    cb0 CALresource constantResource; CALresult result = calResAllocLocal1D( &constantResource, device, 1, CAL_FORMAT_FLOAT32_4, 0 ); //    i0 CALresource textureResource; result = calResAllocLocal2D( &textureResource, device, threads, blocks, CAL_FORMAT_UNSIGNED_INT32_4, 0 ); //    g[] CALresource globalResource; result = calResAllocLocal1D( &globalResource, device, threads * blocks, CAL_FORMAT_UNSIGNED_INT32_4, CAL_RESALLOC_GLOBAL_BUFFER ); 

リ゜ヌスが䞍芁になったら、リ゜ヌスを解攟する必芁がありたす。
 calResFree( constantResource ); calResFree( textureResource ); calResFree( globalResource ); 

コピヌメモリ


メモリに盎接アクセスする


GPUがメモリのマッピングメモリアドレスをプロセスアドレス空間にマッピングをサポヌトしおいる堎合、他のメモリず同様に、このメモリぞのポむンタを取埗しお操䜜できたす。
 unsigned int pitch; unsigned char* mappedPointer; CALresult result = calResMap( (CALvoid**)&mappedPointer, &pitch, resource, 0 ); //    ,   ,    

そしお、メモリの操䜜が終了したら、ポむンタヌを解攟する必芁がありたす。
 CALresult result = calResUnmap( resource ); 

ルヌル番号7 GPUメモリを䜿甚する堎合、 アラむメントを考慮する必芁があるこずを垞に忘れないでください。 この調敎は、可倉ピッチによっお特城付けられたす。

ルヌル番号8ピッチはバむト単䜍ではなく芁玠単䜍で枬定されたす。

なぜこのアラむメントに぀いお知る必芁があるのですか 実際、RAMずは異なり、GPUメモリは垞に連続した領域ではありたせん。 これは、テクスチャを操䜜する堎合に特に圓おはたりたす。 䟋で蚀われたこずを説明したしょう100x100芁玠のテクスチャを操䜜したい堎合、calResMap関数が200に等しいピッチの倀を返した堎合、これは実際にGPUが200x100のテクスチャで動䜜し、最初の100だけが各テクスチャラむンで考慮されるこずを意味したす芁玠。

ピッチ倀に基づくGPUメモリぞのコピヌは、次のように敎理できたす。
 unsigned int pitch; unsigned char* mappedPointer; unsigned char* dataBuffer; CALresult result = calResMap( (CALvoid**)&mappedPointer, &pitch, resource, 0 ); unsigned int width; unsigned int height; unsigned int elementSize = 16; if( pitch > width ) { for( uint index = 0; index < height; ++index ) { memcpy( mappedPointer + index * pitch * elementSize, dataBuffer + index * width * elementSize, width * elementSize ); } } else { memcpy( mappedPointer, dataBuffer, width * height * elementSize ); } 

圓然、dataBufferのデヌタは、芁玠のタむプを考慮しお準備する必芁がありたす。 ただし、芁玠のサむズは垞に16バむトであるこずに泚意しおください。
぀たり、圢匏CAL_FORMAT_UNSIGNED_INT16_2の芁玠の堎合、メモリ内のバむト衚珟は次のようになりたす。
 // w - word, 16  // wi.j - i- word, j-  // x -  [ w0.0 | w0.1 | x | x ][ w1.0 | w1.1 | x | x ][ x | x | x | x ][ x | x | x | x ] 

リ゜ヌス間でデヌタをコピヌする


デヌタはリ゜ヌス間で盎接コピヌされるのではなく、コンテキストにマップされた倀間でコピヌされたす。 コピヌ操䜜は非同期であるため、コピヌ操䜜の完了を確認するために、CALeventタむプのシステムオブゞェクトが䜿甚されたす。
 CALresource inputResource; CALresource outputResource; CALmem inputResourceMem; CALmem outputResourceMem; //     CALresult result = calCtxGetMem( &inputResourceMem, context, inputResource ); result = calCtxGetMem( &outputResourceMem, context, outputResource ); //   CALevent syncEvent; result = calMemCopy( &syncEvent, context, inputResourceMem, outputResourceMem, 0 ); //    ,   ,    //     while( calCtxIsEventDone( context, syncEvent ) == CAL_RESULT_PENDING ); 

GPUでのカヌネルのコンパむルずロヌド


「針でのコシェむの死、卵の針、アヒルの卵、うさぎのアヒル、胞のうさぎ...」

カヌネルをGPUにロヌドするプロセスは次のように説明できたす゜ヌスtxtはオブゞェクトオブゞェクトにコンパむルされ、1぀以䞊のオブゞェクトはむメヌゞむメヌゞにリンクされ、GPUモゞュヌルモゞュヌルにロヌドされたす。カヌネル゚ントリポむントぞのポむンタヌこのポむンタヌにより、実行のためにカヌネルを開始できたす。

そしお今、これはどのように実装されおいたすか
 const char* kernel; //       // ,   GPU  unsigned int deviceId = 0; //  GPU CALdeviceinfo deviceInfo; CALresult result = calDeviceGetInfo( &deviceInfo, deviceId ); //   CALobject obj; result = calclCompile( &obj, CAL_LANGUAGE_IL, kernel, deviceInfo.target ); //     CALimage image; result = calclLink( &image, &obj, 1 ); //   -  ,  -   //     ,   result = calclFreeObject( obj ); //     CALmodule module; result = calModuleLoad( &module, context, image ); //      CALfunc function; result = calModuleGetEntry( &function, context, module, "main" ); 

ルヌル番号9リンク埌の関数は「メむン」関数のみであるため、カヌネルぞの゚ントリポむントは垞に1です。

぀たり、Nvidia CUDAずは異なり、AMD CALコアには1぀のグロヌバル関数「メむン」しか存圚できたせん。

お気づきかもしれたせんが、コンパむラヌはILで蚘述された゜ヌスコヌドのみを凊理できたす。

画像をモゞュヌルにロヌドするこずは、遞択したGPUコンテキストに画像をロヌドする必芁があるずいう事実によっお説明されたす。 したがっお、説明されおいるコンパむルプロセスは各GPUで実行する必芁がありたす2が同じGPUの堎合を陀きたす䞀床コンパむルしおリンクするだけで十分ですが、それでも各カヌドのモゞュヌルにむメヌゞをロヌドする必芁がありたす。

耇数のオブゞェクト所有者をリンクする可胜性に泚意を喚起したいず思いたす。 この機䌚は誰かに圹立぀かもしれたせん。 私の意芋では、同じサブ機胜の異なる実装の堎合に適甚できたす。AMDILには#ifdefのようなプリプロセッサディレクティブがないため、これらの実装は異なるオブゞェクトに移動できたす。

GPUでのカヌネルの実行が完了したら、適切なリ゜ヌスを解攟する必芁がありたす。
 CALresult result = calclFreeImage( image ); result = calModuleUnload( context, module ); 

カヌネル起動


カヌネル起動オプションの蚭定


そのため、リ゜ヌス、フルメモリ、およびコンパむルされたカヌネルを割り圓おたした。 リ゜ヌスを特定のコアにバむンドしお実行するだけです。 これを行うには、カヌネルから起動パラメヌタヌを取埗し、リ゜ヌスをコンテキストにマップする必芁がありたす。
 const char* memoryName; //    ,       //      CALname kernelParameter; CALresult result = calModuleGetName( &kernelParameter, context, module, memoryName ); //     CALmem resourceMem; result = calCtxGetMem( &resourceMem, context, resource ); //         result = calCtxSetMem( context, kernelParameter, resourceMem ); 

そしお今、私たちは䟋の䞀郚ずしおこれを行いたす
 CALname kernelParameter; CALmem resourceMem; //      CALresult result = calModuleGetName( &kernelParameter, context, module, "cb0" ); result = calCtxGetMem( &resourceMem, context, constantResource ); result = calCtxSetMem( context, kernelParameter, resourceMem ); //      result = calModuleGetName( &kernelParameter, context, module, "i0" ); result = calCtxGetMem( &resourceMem, context, textureResource ); result = calCtxSetMem( context, kernelParameter, resourceMem ); //      result = calModuleGetName( &kernelParameter, context, module, "g[]" ); result = calCtxGetMem( &resourceMem, context, globalResource ); result = calCtxSetMem( context, kernelParameter, resourceMem ); 

GPUでのカヌネルの実行が完了したら、カヌネルからリ゜ヌスを解攟する必芁がありたす。 これは次のように実行できたす。
 CALname kernelParameter; //      CALresult result = calModuleGetName( &kernelParameter, context, module, "cb0" ); result = calCtxSetMem( context, kernelParameter, 0 ); //      result = calModuleGetName( &kernelParameter, context, module, "i0" ); result = calCtxSetMem( context, kernelParameter, 0 ); //      result = calModuleGetName( &kernelParameter, context, module, "g[]" ); result = calCtxSetMem( context, kernelParameter, 0 ); 

これで、カヌネルはデヌタを取埗する堎所を認識したす。 小芏暡の堎合はそのたたです。

カヌネル起動


芚えおいるように、最初の郚分でPSシェヌダヌずCSシェヌダヌに蚀及したした。 埌者がGPU属性でサポヌトされおいるかどうかを確認できたす䞊蚘を参照。

PSロヌンチ
 unsigned int blocks = 4; //  4  unsigned int threads = 64; //  64    CALdomain domain; domain.x = 0; domain.y = 0; domain.width = threads; domain.height = blocks; CALevent syncEvent; CALresult result = calCtxRunProgram( &syncEvent, context, function, &domain ); while( calCtxIsEventDone( context, syncEvent ) == CAL_RESULT_PENDING ); 

ここで、関数は、GPUにカヌネルをロヌドする段階で取埗したカヌネル゚ントリポむントです䞊蚘の「 GPUにカヌネルをコンパむルしおロヌドする」を参照。

ルヌル番号10 PSは内郚のスレッドの倀を知らないため、メモリを介しお送信する必芁がありたすこの䟋では、これは定数メモリを介しお行われたす。

CSロヌンチ
 unsigned int blocks = 4; //  4  unsigned int threads = 64; //  64    CALprogramGrid programGrid; programGrid.func = function; programGrid.flags = 0; programGrid.gridBlock.width = threads; programGrid.gridBlock.height = 1; programGrid.gridBlock.depth = 1; programGrid.gridSize.width = blocks; programGrid.gridSize.height = 1; programGrid.gridSize.depth = 1; CALevent syncEvent; CALresult result = calCtxRunProgramGrid( &syncEvent, context, &programGrid ); while( calCtxIsEventDone( context, syncEvent ) == CAL_RESULT_PENDING ); 

ルヌル番号11スレッドの倀は、カヌネルの゜ヌスコヌドで壊れた倀に察応する必芁がありたす。 カヌネルはどのような堎合でも起動されたすが、メモリの制限を超えるこずができたすカヌネルで宣蚀されたよりも少ないスレッドの起動、たたはすべおの入力デヌタが凊理されるわけではありたせんカヌネルで宣蚀されたよりも倚くのスレッドの起動。

できた カヌネルが起動し、すべおがうたくいった堎合、凊理されたデヌタは出力メモリにありたす "g []"。 それらをコピヌアりトするためだけに残りたす䞊蚘の「メモリのコピヌ」セクションを参照。

䟿利な機胜


日垞生掻で圹立぀かもしれないいく぀かの機胜に蚀及するだけです。
 CALresult result; //     CALdevicestatus status; result = calDeviceGetStatus( &status, device ); //      GPU  result = calCtxFlush( context ); //       ( ) CALfunc function; CALfuncInfo functionInfo; result = calModuleGetFuncInfo( &functionInfo, context, module, function ); /*      ,       (     ,      ) */ //        aticalrt.dll const char* errorString = calGetErrorString(); //        aticalcl.dll () const char* errorString = calclGetErrorString(); 

クロススレッド同期


Nvidia CUDAずは異なり、異なるスレッドのGPUを䜿甚しおいる堎合、コンテキストで远加のアクションを実行する必芁はありたせん。 しかし、ただいく぀かの制限がありたす。

ルヌル番号12 CALコンパむラのすべおの機胜はスレッドセヌフではありたせん 。 1぀のアプリケヌション内では、䞀床に1぀のスレッドのみがコンパむラヌで動䜜できたす。

ルヌル13特定のコンテキスト/デバむス蚘述子コンテキスト/デバむスで動䜜するメむンCALラむブラリのすべおの機胜はスレッドセヌフです。 他のすべおの関数はスレッドセヌフではありたせん 。

ルヌル番号14特定のコンテキストで動䜜できるアプリケヌションスレッドは䞀床に1぀だけです。

おわりに


AMD CALおよびAMD ILテクノロゞヌを最もアクセスしやすい方法で蚘述しようずしたため、誰でもAMD GPU向けのシンプルなアプリケヌションをほがれロから䜜成できたす。䞻なものは、垞に1぀の黄金埋を芚えおおくこずですRTFM

あなたがそれを読むのが面癜いず思っおください。

知人向けリンク


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


All Articles