Как использовать C++ AMP из C#Источник: habrahabrru
В Visual Studio 11 Developer Preview, C++ AMP позволяет ускорить Ваши приложения, используя гетерогенное железо, такое как GPU. Если Вы являетесь .NET-разработчиком, то все равно сможете использовать C++ AMP в Ваших приложениях. Большинство кода будет писаться на C#, лишь некоторые участки с помощью C++ AMP для его выполнения на GPU, затем использоваться любимый interop-механизм для связывания. Данный пост объяснит, как это сделать через P/invoke. Однако перед попыткой вызвать C++ AMP из C#, убедитесь, что C++ AMP работает на Вашей машине. Пост VS 11 Developer Preview вместе с C++ AMP от Daniel Moth объясняет, как это сделать. Замечу, что C++ AMP может быть использован как из Visual Studio 11 Express, так и Visual Studio 11 Ultimate, впрочем, в данной статье мы будем использовать последний вариант. Короткий путь Как только C++ AMP заработает на Вашей системе, наиболее простым способом начать использовать его будет открытие примера проекта в Visual Studio 11 Ultimate и начать экспериментировать с ним. Длинный путь Если у Вас существует готовое приложение, которое хотите изменить для возможности использовать C++ AMP, или же хотите понять, как вышеприведенный пример был создан, тогда следуйте описанным ниже шагам. Вкратце, потребуется выполнить следующие действия: Шаг 1: Откройте или создайте C# проект в Visual Studio 11. Итак, перейдем к более подробному описанию необходимых шагов. Шаг 1: Откройте или создайте C# проект в Visual Studio 11 Прежде всего, Вам необходимо открыть или создать C# проект. В остальной части статьи будет подразумеваться, что он назван как HelloWorldCSharp, и создано на основе шаблона Visual C# Console Application. Шаг 2: Добавьте C++ проект к решению Нам также потребуется Win32 DLL, содержащий C++ AMP код. В данном примере, мы создадим "Win32 Console Application" и назовем как "HelloWorldLib": После нажатия Next, выберем тип приложения как "DLL":
Шаг 3: Добавьте шаг сборки проекта для копирования Win32 DLL к бинарникам managed-проекта При сборке решения хотелось бы, чтобы оба проекта собирались, не так ли? Однако, HelloWorldLib.dll не будет скопирован в папку с бинарниками HelloWorldCSharp. Нам необходимо так это сделать, что HelloWorldCSharp.exe смог бы найти во время выполнения. Далее, Вам потребуется отредактировать HelloWorldCSharp.csproj в Visual Studio ( правый клик на проекте, нажимаем "Edit HelloWorldSharp.csproj"):
Вставьте следующий XML прямо перед секцией "Microsoft.CSharp.targets": <ItemGroup> <Content Include="..\$(Configuration)\HelloWorldLib.dll"> <Link>HelloWorldLib.dll</Link> </Content> </ItemGroup> После повторной загрузки HelloWorldLib, HelloWorldLib.dll должна появится в обозревателе решений. Шаг 4: Добавьте зависимости между проектами Для большего удобства, зададим проект HelloWorldLib как зависимость для проекта HelloWorldCSharp. Потом, при сборке HelloWorldCSharp, произойдет сборки и HelloWorldLib. И далее добавим зависимость от HelloWorldLib:
Чтобы удостовериться в правильности сборки решения, произведите повторную сборку проекта, после этого папка бинарников HelloWorldCSharp (т.е., HelloWorldCSharp\HelloWorldCSharp\bin\Debug) должна содержать и HelloWorldCSharp.exe, и HelloWorldLib.dll. Шаг 5: Пишем C++ AMP и C# код Теперь мы готовы для вызова C++ AMP кода из C#. Изменим 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(); } Мы просто добавили функцию square_array, которая возводит в квадрат элементы массива, используя C++ AMP. Также, мы задекорировали функцию, чтобы экспортировать ее из DLL. 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++ AMP код через C#. Замечу, что это весьма простой пример, демонстрирующий возможность вызова C++ AMP функции из C#. Пример слишком "наивный" для демонстрации скорости выполнения - он производит слишком мало действий над элементами данных с использованием возможностей GPU-акселерации. Пост C++ AMP code for Matrix Multiplication является примером, демонстрирующим ускорение при перемножении матриц. От переводчика Кроме C++ AMP существует еще один проект от Microsoft (его подразделения Research) - Accelerator, предоставляющий возможность параллельных вычислений как на многоядерных CPU, так и на GPU, поддерживающим DirectX 9 и выше. |