Visual Studio 11 Developer Previewでは、C ++ AMPを使用すると、GPUなどの異種ハードウェアを使用してアプリケーションを高速化できます。
.NET開発者であれば、アプリケーションでC ++ AMPを引き続き使用できます。 コードの大部分はC#で記述され、C ++ AMPを使用してGPUで実行する一部のセクションのみが記述され、次にバインディングのためのお気に入りの相互運用メカニズムが使用されます。 この投稿では、P / invokeでこれを行う方法を説明します。
ただし、C#からC ++ AMPを呼び出そうとする前に、C ++ AMPがマシンで動作することを確認してください。 ダニエル・モスによるC ++ AMPとVS 11 Developer Previewによる投稿は、これを行う方法を説明しています。 C ++ AMPはVisual Studio 11 ExpressとVisual Studio 11 Ultimateの両方から使用できますが、この記事では最後のオプションを使用します。
ショートカット
C ++ AMPがシステム上で動作を開始したら、Visual Studio 11 Ultimateでサンプルプロジェクトを開き、試してみるのが最も簡単な方法です。
長い道のり
C ++ AMPを使用できるように変更する既製のアプリケーションがある場合、または上記の例がどのように作成されたかを理解する場合は、以下の手順に従います。 つまり、次のことを行う必要があります。
- 手順1:Visual Studio 11でC#プロジェクトを開くか作成します。
- ターゲットプラットフォームをX86として選択します(32ビットC ++ AMPコードを作成する場合)。
- プロジェクトで安全でないコードの使用を許可します。
- ステップ2:C ++プロジェクトをソリューションに追加します。
- C ++ AMPコードを含むWin32 DLLを作成します。
- 手順3:プロジェクトビルド手順を追加して、Win32 DLLを管理対象プロジェクトバイナリにコピーします。
- ステップ4:プロジェクト間に依存関係を追加します。
- ステップ5:C ++ AMPおよびC#コードを作成します。
- C#コードは、C ++ AMPコードにP / invokeを使用します。
それでは、必要なステップのより詳細な説明に移りましょう。
手順1:Visual Studio 11でC#プロジェクトを開くまたは作成する
まず、C#プロジェクトを開くか作成する必要があります。 この記事の残りの部分では、HelloWorldCSharpという名前で、Visual C#コンソールアプリケーションテンプレートに基づいていることを前提としています。
コンソールアプリケーションを作成するにはVisual Studio 11 Ultimateが必要です。なぜなら、 Visual Studio 11 Expressでは、Metroアプリケーションのみを作成できます。
次の2つのパラメーターを明確にする必要がある場合があります。
- C ++ AMPコードは32ビットになることがわかっているため、ターゲットプロジェクトプラットフォームはX86として指定する必要がありますが、AnyCPUは指定しないでください。
- マネージプロジェクトでは、安全でないコードを許可する必要があります(ソリューションエクスプローラーでHelloWorldCSharpプロジェクトを右クリックし、[ビルド]タブをクリックして、[安全でないコードを許可する]を選択します)。
ステップ2:C ++プロジェクトをソリューションに追加する
C ++ AMPコードを含むWin32 DLLも必要です。 この例では、「Win32コンソールアプリケーション」を作成し、「HelloWorldLib」という名前を付けます。
[次へ]をクリックした後、アプリケーションの種類を「DLL」として選択します。
ステップ3:プロジェクトビルドステップを追加して、Win32 DLLを管理プロジェクトバイナリにコピーします
ソリューションを組み立てるときに、両方のプロジェクトを一緒にしたいと思いますか? ただし、HelloWorldLib.dllはHelloWorldCSharpバイナリフォルダーにコピーされません。 実行時にHelloWorldCSharp.exeが見つかるように、これを行う必要があります。
ビルドするたびにHelloWorldLib.dllが正しくコピーされるようにするには、HelloWorldCSharpプロジェクトにビルドステップを追加する必要があります。 まず、ソリューションエクスプローラーでHelloWorldCSharpをアンロードします。
次に、Visual StudioでHelloWorldCSharp.csprojを編集する必要があります(プロジェクトを右クリックし、[HelloWorldSharp.csprojの編集]をクリックします)。
「Microsoft.CSharp.targets」セクションの直前に次のXMLを貼り付けます。
<ItemGroup> <Content Include="..\$(Configuration)\HelloWorldLib.dll"> <Link>HelloWorldLib.dll</Link> </Content> </ItemGroup>
HelloWorldLibを再ロードすると、HelloWorldLib.dllがソリューションエクスプローラーに表示されます。
プロパティウィンドウで、[出力ディレクトリにコピー]が[新しい場合はコピー]として選択されていること、および[ビルドアクション]が[コンテンツ]に設定されていることを確認します。
ステップ4:プロジェクト間に依存関係を追加する
便宜上、HelloWorldLibプロジェクトをHelloWorldCSharpプロジェクトの依存関係として定義します。 次に、HelloWorldCSharpをビルドするときに、アセンブリとHelloWorldLibも発生します。
HelloWorldCSharpを右クリックして、[プロジェクトの依存関係]を選択します。
そして、HelloWorldLibに依存関係を追加します。
ソリューションが正しくビルドされていることを確認するには、プロジェクトを再構築します。その後、HelloWorldCSharpバイナリフォルダー(つまり、HelloWorldCSharp \ HelloWorldCSharp \ bin \ Debug)にHelloWorldCSharp.exeとHelloWorldLib.dllの両方を含める必要があります。
ステップ5:C ++ AMPおよびC#コードの作成
これで、C#からC ++ AMPコードを呼び出す準備ができました。 HelloWorldLib.cppを次のように変更します。
#include "stdafx.h" #include "amp.h" using namespace concurrency; extern "C" __declspec ( dllexport ) void _stdcall square_array(float* arr, int n) { // Create a view over the data on the CPU array_view<float,1> dataView(n, &arr[0]); // Run code on the GPU parallel_for_each(dataView.grid, [=] (index<1> idx) mutable restrict(direct3d) { dataView[idx] = dataView[idx] * dataView[idx]; }); // Copy data from GPU to CPU dataView.synchronize(); }
C ++ AMPを使用して配列の要素を二乗するsquare_array関数を追加しました。 また、DLLからエクスポートするように関数を修飾します。
次に、HelloWorldCSharpアプリケーションを編集して、C ++ AMPコードを呼び出します。 HelloWorldCSharpプロジェクトのProgram.csを次のように変更します。
using System; using System.Runtime.InteropServices; class Program { /// <summary> /// Function defined in HelloWorldLib.dll to square an array using C++ AMP /// </summary> [DllImport("HelloWorldLib", CallingConvention = CallingConvention.StdCall)] extern unsafe static void square_array(float* array, int length); static unsafe void Main() { // Allocate an array float[] arr = new[] { 1.0f, 2.0f, 3.0f, 4.0f }; // Square the array elements using C++ AMP fixed (float* arrPt = &arr[0]) { square_array(arrPt, arr.Length); } // Enumerate the results foreach (var x in arr) { Console.WriteLine(x); } } }
...それだけです! これで、HelloWorldCSharpプロジェクトを開始し、C#でC ++ AMPコードが機能することを確認できます。
これは、C#からC ++ AMP関数を呼び出す機能を示す非常に単純な例です。 この例は、実行速度を示すにはあまりにも「単純」です。GPUアクセラレーションの機能を使用して、データ要素に対して実行するアクションが少なすぎます。 マトリックス乗算ポストのC ++ AMPコードは、マトリックスを乗算するときの加速を示す例です。
翻訳者から
C ++ AMPに加えて、Microsoft(その研究部門)からの別のプロジェクト-Acceleratorがあります。これは、DirectX 9以降をサポートするマルチコアCPUとGPUの両方で並列計算の可能性を提供します。
Accelerator v2は、マネージラッパーを備えたネイティブC ++ライブラリです。