ドライバーのセットアップ
最も長くて難しい部分は、OpenCL用のドライバーのセットアップです。 システムがコンピューターに1年以上使用されている場合、AMDカードがあり、システムのドライバーが更新されていることをすぐに言います。システムの再配置が必要になる可能性があります。
AMD
AMDにはドライバーに関する問題がいくつかありますが、多くの例が含まれたすばらしいSDKがあり、サポートフォーラムは稼働中です。 AMD Catalystの最近のバージョンでは、OpenCLのドライバーは自動的にインストールされます。 SDK for workはこちらから入手できます 。 インストールする前に、グラフィックカードが OpenCLをサポートしているかどうかを確認してください。 AMDの場合、部分的なサポートは4300シリーズから始まり、完全なサポートは5400から始まります。nVidia
原則として、nVidiaのドライバーの問題は少ないですが、時々起きることもあります。 OpenCLのサポートは、8600シリーズ前後から提供されます。 ここからドライバーを入手できます 。Intel
AMDやnVidiaとは異なり、Intelドライバーで問題が発生したことはありません。 ここで取ることができます 。システムにドライバーをインストールしても、ドライバーが機能することは保証されません。 AMDのバグの数は圧倒的です(3台のコンピューターのうち2台にインストールするときに問題が発生します)。nVidiaの場合は大きい(1/3)。 したがって、インストール後、まずOpenCLが接続されているかどうかを確認することをお勧めします。 これは、ビデオカードのパラメータを表示するプログラムを介して最も簡単に実行できます。 私はGpuCapsViewerを使用し、opencl-zとGPU-Zも動作します。
問題が発生した場合...すべての古いドライバーを削除し、再配置します。 AMDの場合-正しいバージョンのドライバーをインストールしてください。 ラップトップドライバーは、多くの場合バグがあります。 問題が解消されていない場合は、Windowsを再インストールすると問題が解決します。
ラッパー
私たちの目標は、C#のOpenCLで可能な限り単純なプログラムを作成することなので、倒錯を処理せずOpenCLヘッダーを接続しますが、開発を簡素化する既製のライブラリを使用します。 私のように、最も完全でバグの多いバージョンは、 OpenTKの一部であるcloo.dllです。 最も使いやすく 、多くの操作を自動化するのはOpenCLTemplateで 、これはclooのアドオンです。 後者のマイナス面のうち、AMD、たとえば最新のドライバー(11.6)を使用する場合、デバイスの初期化を拒否することがあります。 OpenSourceプロジェクト以来、私が抱えていた不具合を見つけて修正しましたが、いつライブラリの新しいバージョンがリリースされるのかわかりません。 また、インターネット上で見つけることができるあまり知られていないラッパーもいくつかあります。
最初のプログラム
最初のプログラムとして、OpenCLを使用して2つのベクトルv1とv2の合計を計算します。 cloo.dllを使用して記述されたプログラム例:
クロプログラム
private void button4_Click( object sender, EventArgs e)
{
// , . Platforms[1]
//
ComputeContextPropertyList Properties = new ComputeContextPropertyList(ComputePlatform.Platforms[1]);
ComputeContext Context = new ComputeContext(ComputeDeviceTypes.All, Properties, null , IntPtr .Zero);
// , (GPU CPU).
// . , C99 OpenCL.
string vecSum = @"
__kernel void
floatVectorSum(__global float * v1,
__global float * v2)
{
int i = get_global_id(0);
v1[i] = v1[i] + v2[i];
}
" ;
// , vecSum
List <ComputeDevice> Devs = new List <ComputeDevice>();
Devs.Add(ComputePlatform.Platforms[1].Devices[0]);
Devs.Add(ComputePlatform.Platforms[1].Devices[1]);
Devs.Add(ComputePlatform.Platforms[1].Devices[2]);
// vecSum
ComputeProgram prog = null ;
try
{
prog = new ComputeProgram(Context, vecSum); prog.Build(Devs, "" , null , IntPtr .Zero);
}
catch
{ }
//
ComputeKernel kernelVecSum = prog.CreateKernel( "floatVectorSum" );
// , .
float [] v1 = new float [100], v2 = new float [100];
for ( int i = 0; i < v1.Length; i++)
{
v1[i] = i;
v2[i] = 2 * i;
}
// .
ComputeBuffer< float > bufV1 = new ComputeBuffer< float >(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v1);
ComputeBuffer< float > bufV2 = new ComputeBuffer< float >(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v2);
// vecSum
kernelVecSum.SetMemoryArgument(0, bufV1);
kernelVecSum.SetMemoryArgument(1, bufV2);
// . , !
ComputeCommandQueue Queue = new ComputeCommandQueue(Context, Cloo.ComputePlatform.Platforms[1].Devices[0], Cloo.ComputeCommandQueueFlags.None);
//. Execute - vecSum (v1.Length)
Queue.Execute(kernelVecSum, null , new long [] { v1.Length }, null , null );
// .
float [] arrC = new float [100];
GCHandle arrCHandle = GCHandle.Alloc(arrC, GCHandleType.Pinned);
Queue.Read< float >(bufV1, true , 0, 100, arrCHandle.AddrOfPinnedObject(), null );
}
* This source code was highlighted with Source Code Highlighter .
以下は、OpenCLTemplate.DLLを介して実装された同じプログラムです。
private void btnOpenCL_Click( object sender, EventArgs e)
{
// , (GPU CPU).
// . , C99 OpenCL.
string vecSum = @"
__kernel void
floatVectorSum(__global float * v1,
__global float * v2)
{
int i = get_global_id(0);
v1[i] = v1[i] * v2[i];
}" ;
// . . GPU.
//OpenCLTemplate.CLCalc.InitCL(Cloo.ComputeDeviceTypes.All)
//GPU CPU.
OpenCLTemplate.CLCalc.InitCL();
// .
List <Cloo.ComputeDevice> L = OpenCLTemplate.CLCalc.CLDevices;
//
OpenCLTemplate.CLCalc.Program.DefaultCQ = 0;
// vecSum
OpenCLTemplate.CLCalc.Program.Compile( new string [] { vecSum });
// , .
OpenCLTemplate.CLCalc.Program.Kernel VectorSum = new OpenCLTemplate.CLCalc.Program.Kernel( "floatVectorSum" );
int n = 100;
float [] v1 = new float [n], v2 = new float [n], v3 = new float [n];
// , .
for ( int i = 0; i < n; i++)
{
v1[i] = i;
v2[i] = i*2;
}
//
OpenCLTemplate.CLCalc.Program.Variable varV1 = new OpenCLTemplate.CLCalc.Program.Variable(v1);
OpenCLTemplate.CLCalc.Program.Variable varV2 = new OpenCLTemplate.CLCalc.Program.Variable(v2);
// ,
OpenCLTemplate.CLCalc.Program.Variable[] args = new OpenCLTemplate.CLCalc.Program.Variable[] { varV1, varV2 };
//
int [] workers = new int [1] { n };
// VectorSum args workers
VectorSum.Execute(args, workers);
//
varV1.ReadFromDeviceTo(v3);
}
* This source code was highlighted with Source Code Highlighter .
ご覧のとおり、2番目のオプションははるかにシンプルで直感的です。
最後のリンク
まず、このサイトはC# -www.cmsoft.com.brを介したOpenCLでのプログラミングに専念しています。 残念ながら、それを導く人はほとんどいないので、例はしばしば不適切であり、サイトの作者によって作成されたOpenCLTemplateは非常にバグが多いです。
便利な場所は、 www.opentk.comのサイトです。そこでは、cloo.dllを介してプログラミングに関する質問に非常に迅速に回答します
sourceforge.net/projects/clooでほぼ同じ答えを得ることができます
C99ベースのOpenClプログラミング標準については、 www.khronos.org / openclで説明しています。
「 OpenClの概要 」という記事の続きでは、ビデオカードのプログラミングに使用するプログラミング言語の機能について説明しています。