Отладка кода GPU
Область применения:Visual Studio Visual Studio для Mac
Visual Studio Code ![]()
Можно выполнять отладку кода C++, который выполняется в графическом процессоре (GPU). Поддержка отладки GPU в Visual Studio включает обнаружение состояния гонки, запуск процессов и присоединение к ним, а также интеграцию с окнами отладчика.
Поддерживаемые платформы
Отладка поддерживается в Windows 7, Windows 8, Windows 10, Windows 11, Windows Server 2008 R2, Windows Server 2012 и Windows Server 2016. Для отладки в программном эмуляторе требуется Windows 8, Windows 10, Windows 11, Windows Server 2012 или Windows Server 2016. Для отладки на оборудовании необходимо установить драйверы для видеокарты. Не все производители оборудования реализуют полный набор функций для отладки. См. информацию об ограничениях в документации производителя.
Независимые производители оборудования, желающие реализовать поддержку отладки GPU в Visual Studio, должны создать библиотеку DLL, реализующую интерфейс VSD3DDebug для взаимодействия с драйверами производителей.
Настройка отладки GPU
Отладчик не может прерывать выполнение одновременно кода ЦП и кода GPU при работе одного приложения. По умолчанию отладчик прерывает выполнение кода ЦП. Для отладки кода GPU следует выполнить одно из указанных ниже действий.
- В списке Тип отладки панели инструментов Стандартная выберите Только GPU.
- Откройте контекстное меню для своего проекта в области Обозреватель решений и выберите Свойства. В диалоговом окне Страницы свойств выберите Отладка, после чего выберите Только GPU в списке Тип отладчика.
Запуск приложений и присоединение к ним
Для запуска и остановки отладки GPU можно использовать команды отладки Visual Studio. Дополнительные сведения см. в статье Навигация по коду с помощью отладчика. Можно также присоединить отладчик GPU к выполняющемуся процессу, но лишь при условии, что этот процесс выполняет код GPU. См. сведения о присоединении к выполняемым процессам.
Команды «Выполнить текущий Tile до курсора» и «Выполнить до текущей позиции»
При отладке кода GPU существуют два варианта выполнения кода до текущего положения курсора. Команды для обоих вариантов доступны в контекстном меню редактора кода.
- По команде Выполнить до текущей позиции приложение выполняется до достижения текущей позиции курсора, после чего выполнение приостанавливается. Это не означает, что текущий поток будет выполнен до позиции курсора. Инициировать приостановку выполнения может любой поток, который первым достигнет текущего положения курсора. См. статью Навигация по коду с помощью отладчика.
- По команде Выполнить текущий блок до курсора приложение выполняется до тех пор, пока все потоки в текущем блоке потоков (tile) не достигнут курсора, после чего выполнение приостанавливается.
Окна отладки
С помощью некоторых окон отладки можно просматривать, помечать и замораживать потоки GPU. Дополнительные сведения см. в разделе:
- Использование окна «Параллельные стеки»
- Использование окна задач
- Практическое руководство. Использование окна контроля параллельных данных
- Отладка потоков и процессов (панель инструментов «Место отладки»)
- Практическое руководство. Использование окна потоков GPU
Исключения синхронизации данных
Отладчик может распознавать несколько условий синхронизации данных во время выполнения. При обнаружении условия отладчик переходит в состояние приостановки выполнения. На выбор предлагаются два варианта действий: Прервать или Продолжить. В диалоговом окне Исключения предусмотрены параметры, с помощью которых можно указать, должен ли отладчик распознавать эти условия и при каких из этих условий он должен прерывать выполнение. Дополнительные сведения см. в статье Управление исключениями с помощью отладчика. В диалоговом окне Параметры также есть возможность указать, что отладчик должен игнорировать исключения, если записываемые данные не изменяют значения данных. Для получения дополнительной информации см. General, Debugging, Options Dialog Box.
Устранение неполадок
Определение ускорителя
Точки останова в коде GPU распознаются, только если код выполняется на ускорителе accelerator::direct3d_ref (REF). Если ускоритель в коде не указывается, в свойствах проекта в качестве значения Тип ускорителя отладки будет автоматически выбран ускоритель REF. Если ускоритель явным образом указывается непосредственно в коде, ускоритель REF во время отладки использоваться не будет и точки останова не будут распознаваться, если только поддержка отладки не предусмотрена в самом оборудовании GPU. Выходом из этой ситуации может быть создание собственного кода, который будет использовать ускоритель REF во время отладки. Дополнительные сведения см. в свойствах проекта, а также статьях Использование объектов accelerator и accelerator_view и Параметры проекта для конфигурации отладки C++.
Условные точки останова
Условные точки останова в коде GPU поддерживаются, но не каждое выражение может быть вычислено на устройстве. Если выражение не может быть вычислено на устройстве, оно вычисляется в отладчике. Отладчик, вероятно, работает медленнее, чем устройство.
Ошибка: Возникла проблема конфигурации с выбранным типом акселератора отладки.
Эта ошибка возникает, если значения параметров проекта не соответствуют конфигурации компьютера, на котором производится отладка. Дополнительные сведения см. в статье Параметры проекта для конфигурации отладки C++.
Ошибка: На целевом компьютере не установлен драйвер отладки для выбранного типа акселератора отладки.
Эта ошибка происходит при отладке на удаленном ПК. Пока не будет начато выполнение, отладчик не может определить, установлены ли драйверы на удаленном ПК. Драйверы предоставляются производителем видеоадаптера.
Ошибка: На удаленном сайте необходимо отключить механизм обнаружения и исправления зависания во время ожидания (TDR).
При выполнении вычислений C++ AMP существует вероятность превышения контрольного времени ожидания, установленного предусмотренным в Windows механизмом обнаружения и исправления зависаний (TDR). При возникновении этой ошибки вычисления прекращаются и данные утрачиваются. Дополнительные сведения см. в разделе Обработка ошибок TDR в C++ AMP.
См. также
- Пошаговое руководство. Отладка приложения C++ AMP
- Параметры проекта для конфигурации отладки C++
- Запуск отладки GPU в Visual Studio
OpenCL. Как начать
Всем привет! Какое-то время назад я начал копать тему с OpenCL под C#. Но наткнулся на трудности, связанные с тем, что не то, что под C#, а вообще по этой теме очень мало материала. Какую-то вводную по OpenCL можно почерпнуть здесь. Так же простой, но работающей старт OpenCL описан вот тут. Ни на йоту не хочу обидеть авторов, но все статьи, что я находил на русском (и на хабре в том числе) страдают одной и той же проблемой — очень мало примеров. Документация есть, её много и как принято для хорошей документации читается сложно. В своей статье (а если всё будет нормально, то и в цикле статей), я постараюсь поподробней описать эту область, с точки зрения человека, который начал её копать с нуля. Думаю такой подход будет полезен тем кто хочет быстро стартовать в высоко производительных вычислениях.
Первоначально я хотел написать статью-минисамоучитель OpenCL, которая содержала в себе информацию, о там что это, как устроено, как писать код и какие-то рекомендации, основанные на моем опыте. Но в процессе понял, что если даже быть кратким, то уткнусь в ограничения объема статьи. Потому что, имхо, статья должна быть такого объема, чтобы усвоить её объем было не сложно. По этому в данной статье (которая станет первой) я планирую описать, то как стартовать в OpenCL, проверить что локально все корректно законфигурино, и написать простейшую программу. Вопросы с устройством памяти, архитектурой и прочим будут описаны в следующих статьях.
Друзья, сразу хотел бы сказать, что мой опыт в OpenCL пока, к сожалению, далек от гуру/йода уровня, но на вопросы постараюсь отвечать изо всех сил. А если что-то не знаю, то буду делиться ресурсами и видением того как это на самом деле должно работать.
Что. Где. Как.
OpenCL это технология связанная с параллельными компьютерными вычислениями на различных типах графических и центральных процессоров. Тема с параллельным вычислениями на GPU совсем недавно широко продвигалась вместе с технологией CUDA. Данное продвижение в основном обеспечивалось усилиями компании Nvidia. Отличия OpenGL и CUDA уже широко обсуждались.
OpenСL позволяет работать как с CPU так и с GPU, но думаю нам более интересно будет сосредоточиться на работе с GPU. Для использования данной технологии понадобиться мало мальски современная видеокарта. Главное это проверить, что устройство функционирует нормально. На всякий случай напоминаю что это можно сделать в диспетчере устройств.

Если в данном окне вы видите какие-то фейлы или ворнинги, то вам прямая дорога на сайт производителя вашей видеокарты. Свежие драйвера должны решить проблему с функционированием железа и как следствие дать доступ к мощностям OpenCL.
Первоначально я планировал использовать OpenCL по C#. Но наткнулся на проблему, что все существующие фреймворки типа Cloo или OpenCLNet являются самописными и Khronos не имеет к ним никакого отношения и следовательно не гарантирует их стабильную работу. Ну и все мы помним главную проблему — очень мало примеров. Исходя из этого вначале я бы хотел представить примеры написанные на C++, а уже потом, получив подтверждение того что OpenCL ведет себя так как мы ожидаем, привинтить прокси в виде C# фреймворка.
Итак, чтобы использовать OpenCL через С++ необходимо найти его API. Для этого открывайте переменные среды, и ищете там переменную со страшным названием, намекающую своим названием на производителя вашей видеокарты. У меня данная переменная называется «AMDAPPSDKROOT». После этого можете посмотреть что лежит по указанному пути. Там ищите папочку include\CL.

Кстати, обычно в папочки include, рядом с папкой CL лежит и папка GL, предоставляющая доступ к знаменитой графической библиотеки.
Теперь создаем проект в Visual Studio, подключаем в свойствах проекта папку include (в моем случае $(AMDAPPSDKROOT)\include\) и в бой!
Инфраструктура
- При помощи API получаем доступ к устройствам, которые поддерживают OpenCL. Это часть приложения обычно называется хостом;
- Пишем код который будет выполняться на устройстве. Этот код называется kernel. Данный код о хосте вообще ничего не знает. Его может дернуть любой хост
- При помощи API прогружаем код kernel и запускаем его выполнение на выбранном устройстве.
Так как на предыдущем шаге мы предусмотрительно подсоединили папочку include, то теперь вы можем просто добавить ссылку на заголовочный файл cl.h, который даст доступ к API. При добавление cl.h, стоит добавить проверку выбора платформы:
#ifdef __APPLE__ #include #else #include #endif
Теперь необходимо выбрать устройство на котором будет отрабатывать наш код и создать контекст в котором будут жить наши переменные. Как это сделать показано ниже:
/* получить доступные платформы */ ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms); /* получить доступные устройства */ ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices); /* создать контекст */ context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret); /* создаем команду */ command_queue = clCreateCommandQueue(context, device_id, 0, &ret);
- CL_DEVICE_TYPE_CPU — запросит существующие CPU.
- CL_DEVICE_TYPE_GPU — запросит существующие GPU.
Kernel
- Код который, будет дергаться с хостовой части, для исполнения, должен начинаться с ключевого слова __kernel;
- Функция с ключевым словом __kernel всегда возвращает void;
- Существуют квалификаторы типов памяти: __global, __local, __constant, __private, которые будут определять, в какой памяти будут храниться переменные. Если квалификатора перед переменной нет, то она является __private;
- «Общение» между хостом и kernel будет через параметры kernel. Чтобы kernel мог что-то передать хосту через параметр, параметр должен быть с квалификатором __global (пока будем использовать только __global);
- Код kernel принято хранить в файле с расширением cl. Но по сути подобный код может генерироваться и на лету. Это позволяет обойти некоторые ограничения. Но об этом в другой раз 🙂
__kernel void test(__global int* message) < // получаем текущий id. int gid = get_global_id(0); message[gid] += gid; >
Что делает данный код. Первое — получает глобальный id work-item который сейчас выполняется. Work-item — это то что и выполняет наш kernel. Так как мы имеем дела с параллельными вычислениями, то для каждого work-item создается свой kernel который ничего не знает о других. И никто не может гарантировать в каком порядке все work-item отработают. Но об этом подробней будет в отдельной статье (уже утал это повторять). В нашем примере это по сути индекс элемента в массиве, потому что мы будем каждый элемент массива обрабатывать в отдельном work-item. Думаю вторую строчку строчку в kernel комментировать излишни 🙂
Формируем kernel
Следующий шаг скомпилировать, то что лежит в файле *.cl. Делается это следующим образом:
cl_program program = NULL; cl_kernel kernel = NULL; FILE *fp; const char fileName[] = "../forTest.cl"; size_t source_size; char *source_str; int i; try < fp = fopen(fileName, "r"); if (!fp) < fprintf(stderr, "Failed to load kernel.\n"); exit(1); >source_str = (char *)malloc(MAX_SOURCE_SIZE); source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp); fclose(fp); > catch (int a) < printf("%f", a); >/* создать бинарник из кода программы */ program = clCreateProgramWithSource(context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret); /* скомпилировать программу */ ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL); /* создать кернел */ kernel = clCreateKernel(program, "test", &ret);
Типы cl_program и cl_kernel определены в cl.h. Сам сценарий довольно прост — загружаем файл, создаем бинарник (clCreateProgramWithSource) и компилируем. Если переменная ret по прежнему содержит 0, то вы все сделали правильно. И останется только создать сам kernel. Важно, чтобы имя передаваемое в команду clCreateKernel, совпадало с именем kernel в файле cl. В нашем случае это «test».
Параметры
Я уже упоминал, что «общения» kernel с хостом происходит за счет записи/чтения в параметры, которые передаются в kernel. В нашем случае это параметр message. Параметры, которые позволяют вот так общаться хосту с kernel, называются буферами(buffer). Давайте создадим такой буфер на стороне хоста и передадим в kernel через API:
cl_mem memobj = NULL; int memLenth = 10; cl_int* mem = (cl_int *)malloc(sizeof(cl_int) * memLenth); /* создать буфер */ memobj = clCreateBuffer(context, CL_MEM_READ_WRITE, memLenth * sizeof(cl_int), NULL, &ret); /* записать данные в буфер */ ret = clEnqueueWriteBuffer(command_queue, memobj, CL_TRUE, 0, memLenth * sizeof(cl_int), mem, 0, NULL, NULL); /* устанавливаем параметр */ ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj);
Важно отметить константу CL_MEM_READ_WRITE, она означает, что мы у нас есть права для буфера на чтение и запись, на стороне kernel. Так же могут быть использованы константы типа CL_MEM_WRITE_ONLY, CL_MEM_READ_ONLY и др. Так же в методе clSetKernelArg, важен второй аргумент, он содержит индекс параметра. В данном случае 0, так как параметр message идет первым в сигнатуре kernel. Если бы он шел вторым, то мы бы написали:
/* устанавливаем параметр */ ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&memobj);
clEnqueueWriteBuffer записывает данные из массива mem в буфер memobj.
Ну что в целом все готово. Осталось только выполнить kernel.
Исполняем kernel
Погнали, отправляем код на исполнение:
size_t global_work_size[1] = < 10 >; /* выполнить кернел */ ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, global_work_size, NULL, 0, NULL, NULL); /* считать данные из буфера */ ret = clEnqueueReadBuffer(command_queue, memobj, CL_TRUE, 0, memLenth * sizeof(float), mem, 0, NULL, NULL);
global_work_size содержит число work-item которые будут созданы. Я уже говорил, что на обработку каждого элемента массива у нас будет свой work-item. Элементов в массиве у нас 10, следовательно work-item содержит 10. clEnqueueNDRangeKernel особых вопросов порождать не должна — просто запускает указанный kernel заданное число раз. clEnqueueReadBuffer считывает данные из буфера с именем memobj и помещает данные в массив mem. Данные в mem и есть наш результат!
Итоги и выводы
Друзья, вот так я представляю старт в OpenCL для новичка. Надеюсь на ваши конструктивные замечания в комментариях, чтобы можно было внести апдейты в будущем. Я пытался быть кратким, но все равно объем вышел не маленький. Так что могу сказать, что материала для 2-3 статей найти еще смогу.
Спасибо, всем кто дочитал до конца!
OpenCL для Visual Studio
OpenCL удобный инструмент для программирования параллельных вычислений на базе GPU, однако установить его не так просто, но не из-за множества тонких настроек, а из-за того, что информации почти нет.
OpenCL — обновленный стандарт для разработки приложений для гетерогенных систем. CUDA является более зрелым в этом плане стандартом, но он проигрывает в скорости.
Как установить OpenCL?
Первое, что вам нужно — это CUDA. если у вас графическая карта на базе NVIDIA, то у них есть все необходимые установщики, а устанавливать саму CUDA достаточно просто, единственное, не ставьте самую последнюю версию, так как она не всегда подходит.
После этого при обновлении visual studio у вас появится инструмент для разработки на CUDA, хотя в будущем самой кудой нам пользоваться не придется (если конечно вы не будете на ней программировать).
При разработке на OpenCL вам необходимо будет использовать cpp файлы, в которые уже всё и подключается.
Для того, чтобы подключить OpenCL, необходимо, зайти в Проект -> Свойства.

В открывшемся окне необходимо выбрать C/C++ -> Общие.
В данной вкладке будет строка: Дополнительные каталоги включаемых файлов. В это место нужно добавить папку, в которой находится CUDA. Вам необходимо найти папку NVIDIA GPU Computing Toolkit\CUDA\v9.2\include;
Необходимо скопировать весь путь. Т.е С:\Program Files\NVIDIA GPU…и т. д.
Если вы устанавливали CUDA вдругую папку, то ваш путь может отличаться.

После этого необходимо открыть Компоновщик -> Общие. И в дополнительные каталоги библиотек добавить C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.2\lib\x64;
Где C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA папка, в которой лежит CUDA. Ваш путь может отличаться.
v9.2 — Версия вашей куды, она также может отличаться от той, которая написана здесь.
lib — папка в которой находятся еще 2 папки. Win32 и x64.
x64 — разрядность, которую необходимо запомнить, так как она понадобится в будущем. Можно выбрать и Win32, в конце будет показано, как использовать это.

Затем необходимо выбрать Компоновщик -> Ввод.
В дополнительные зависимости необходимо добавить opencl.lib;

После того, как добавлены все папки осталась последняя настройка. На рисунке выше показано x64. Такой выбор был сделан из-за того, что была выбрана папка x64 в lib.
При выборе Win32 в папке lib необходимо выбирать x86.
Теперь всё настроено, можно писать необходимую вам программу.
OpenCL on Visual Studio : Configuration tutorial for the confused
This write-up details the step by step process to configure OpenCL on Visual Studio and start working with it quickly. It also provides a recent working example to test out our configuration. It, however, does not serve as a OpenCL beginner tutorial. For that, I suggest to look at this excellent article on OpenCL at Dr. Dobb.
Getting Started
OpenCL has a lot of articles, tutorials, blog posts and StackOverflow questions providing a lot of information for beginners to get started. However, many of these tutorials are outdated, don’t fully resolve all issues or miss out some specifics. It took me two days of fiddling to finally have a working OpenCL tutorial in Visual Studio. Hence, this blog post is to help other people save their two days in configuration, aggregated from a lot of sources and only providing those details which work.
System configuration
I have a Intel Core i3 processor with NVIDIA GeForce 710M and 4 GB RAM running on Windows 10 64-bit. I also have Visual Studio 2012 where I will be configuring OpenCL SDK. Same guide can be used for AMD GPUs too with some variations like location of SDK folders.
1. Getting required drives and SDK
Two things are needed here. First, OpenCL runtime for your graphics card. It can be achieved by simply updating NVIDIA’s graphics card. Secondly, OpenCL SDK is needed for compiling OpenCL code. NVIDIA has hidden them under its CUDA toolkit. So, install CUDA toolkit and you will get OpenCL SDK too.
2. Setting up Visual Studio
I have Visual Studio 2012, hence, the configurations are based on that only. Create a new Visual Studio C++ application (any template). Under src, create a new C file by name of main.c. Similarly, create a kernel file by the name of kernel.cl. main.c will contain the host code. kernel.cl will contain the kernel to be executed.
3. Project configurations
OpenCL is suggested to run on 64-bit configurations. However, the created solution would be in 32–bit only. To fix this, right click on the project > Choose Properties in the context menu. A Property Pages window will open.
Click on Configuration Manager on right. In the Configuration Manager window, select from Active solution platform dropdown menu. In the New Solution Platform window, choose x64 as new platform and copy settings option as Win32. This will make the project targeted for 64-bit build.
For OpenCL config, go to C/C++ > General page. For Additional Include Directories , point to include folder inside your CUDA toolkit installation folder.
Other tutorials on the internet suggest than instead of full path, one can also provide environmental variable $(CUDA_INC_PATH) here( It is automatically created when the toolkit is installed). I, however, found that on doing, Visual Studio’s IntelliSense and auto-complete features will fail to recognise OpenCL code, and mark whole codebase with errors(even though compilation would be successful). Hence, it is best to provide direct path to the include folder instead as done above.
Next in Property Pages, go to Linker > Input and add OpenCL.lib to Additional dependencies.
Lastly, in Linker > General option page, add environmental variable $(CUDA_LIB_PATH) for Additional Library Directories. This variable contains the path to the directory containing OpenCL.dll(It is also automatically created with CUDA toolkit installation).
With this, we have completed configurations. Now, to code.
4. Adding code to the project
Since, this is not a OpenCL programming tutorial, hence, I would suggest you to copy main.c code from here and kernel.cl code from here. Since, the original main.c picks up code from vector_add_kernel.cl but we have kernel.cl, hence change the filename in main.c
30: fp = fopen("vector_add_kernel.cl", "r"); replace it with30: fp = fopen("kernel.cl", "r");
5. Running the program
Press F5 to compile and run the program. If no compilation error, it will create a Debug build of the program and launch it.
A quick reminder here that since it is VS2012, it only supports C89 formats. Hence, if your code is incompatible with C89, it will throw error. It has been fixed from VS2013 though. Many examples on the internet simply fail to compile because of this reason. Hence, this example has been selected for showcasing here because it is C89 compliant.
A command prompt will open up quickly, print some messages and exit quickly. If you want to prevent the command prompt window from closing down you can do the following.
Open the Property pages of the project again. Goto Linker > System page. Change the SubSystem property to Console (/SUBSYSTEM:CONSOLE).
Now, try to launch the program again as a Release build by pressing Ctrl + F5. The program will launch in command prompt but will not exit automatically and will wait for a key press to exit.
6. Few thoughts over the code
This code has been ported from here with changes incorporated from Dr. Doob’s article’s code . The original code was not detecting my NVIDIA platform. Hence, I changed the API to fetch platform information differently.
// Get platform and device information
cl_platform_id platform_id = NULL;
cl_device_id device_id = NULL;
cl_uint ret_num_devices;
cl_uint ret_num_platforms;
cl_int ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
ret = clGetDeviceIDs( platform_id, CL_DEVICE_TYPE_GPU, 1,
&device_id, &ret_num_devices);
This did not work and failed to find NVIDIA plaform. Setting CL_DEVICE_TYPE_GPU to CL_DEVICE_TYPE_DEFAULT or CL_DEVICE_TYPE_ALL made the program choose Intel CPU which got stuck at building kernel, for reasons unknown.
Hence, I changed the code to the following which is more general form of finding OpenCL-compatible plaforms.
// Get platform and device informationcl_device_id device_id = NULL;cl_uint ret_num_devices;cl_uint ret_num_platforms;cl_int ret = clGetPlatformIDs(0, NULL, &ret_num_platforms);cl_platform_id *platforms = NULL;platforms = (cl_platform_id*)malloc(ret_num_platforms*sizeof(cl_platform_id));ret = clGetPlatformIDs(ret_num_platforms, platforms, NULL);printf("ret at %d is %d\n", __LINE__, ret);ret = clGetDeviceIDs( platforms[1], CL_DEVICE_TYPE_ALL, 1,&device_id, &ret_num_devices);
clGetPlatformIDs(0, NULL, &ret_num_platforms); returns the number of platforms. This information is used to allocate memeory for cl_platform_id *platforms. A second call to clGetPlatformIDs(ret_num_platforms, platforms, NULL); populates platforms with data.
One can print the values of platforms but I didn’t . platforms[0] is Intel CPU and platforms[1] is NVIDIA GPU. Hence, I have selected it for clGetDeviceIDs call.
Conclusion
If you have made it this far, then congratulations. I have tried to provide a simple configuration guide for setting up OpenCL on Visual Studio. Though the example uses NVIDIA GPUs, same instructions should apply to AMD GPUs as well. OpenCL documentation and support is really fragmented and it can be daunting task to figure out its nuances. I hope this post can help a person from hair pulling kind of experience I went through , while trying to learn OpenCL. Comments for improvement are always welcome.
Some really good resources for OpenCL whose ideas this post uses :
Streamcomputing blog: Probably the best resource for OpenCL related stuff on the internet
Dr Dobb Gentle introduction to OpenCL : Best beginner’s guide to OpenCL concepts
Erik Smistad ‘s OpenCL hello world program : The base example used in this post
Introduction to OpenCL slides : Most concise way to learn OpenCL concepts quickly
