Getting started with OpenCL on Microsoft Windows

Getting started with OpenCL on Microsoft Windows

Get started with OpenCL on Microsoft Windows

OpenCL is not native to the Windows operating system, and as such isn’t supported across the board of UWP (Universal Windows Platform) platforms (XBox, Hololens, IoT, PC) and the Microsoft Store. Windows as a traditional content creating platform however can build and execute OpenCL applications when built as traditional Win32 GUI or console applications.

OpenCL is not native to the Windows operating system and therefore does not support UWP (Universal Windows Platform) platforms (XBox, Hololens, IoT, PC) and Microsoft Store. However, Windows, as a traditional content creation platform, can build and execute OpenCL applications when built as a traditional Win32 GUI or console application.

(NOTE: Nothing prevents from using advanced WinRT capabilities to use the ICD in packaged applications (APPX/MSIX), however such applications will most certainly not be able to load a functioning OpenCL runtime on platforms other than PC and a few IoT devices.)

(Note: There is nothing to prevent using advanced WinRT features in packaged applications (APPX/MSIX) to use ICD, but these applications will certainly not be able to load a functioning OpenCL on platforms other than PCs and some IoT devices runtime.)

In this guide we’re minimally going to use the following tools:

In this guide, we will use the following tools minimally:

  • The command-line
  • Command Line
  • C/C++ compiler
  • C/C++ compiler

And depending on which ways one extends the bare minimum:

According to the minimal way of extending:

  • CMake (Cross-platform Make)
  • CMake (cross-platform Make)
  • Git
  • Vcpkg (Cross-platform package management)
  • Vcpkg (cross-platform packaging management)
  • Visual Studio Code
  • Visual Studio Code

Steps will be provided to obtain a minimal and productive environment.

Steps will be taken to obtain a minimum production environment.

Installation

Installation

In this guide we’ll be using latest (at the time of writing) Windows 10. Installation for the most part will happen via winget, the 1st party command-line tool for installing software on Windows. If for whatever reason you do not have the winget client on your PATH, it is bundled with the App Installer package in the Microsoft Store. Updating this component should also install the command-line tool.

?In this guide, we will be using the latest (at the time of writing) Windows 10. Most of the installation will be done through winget, a first-party command line tool for installing software on Windows. For whatever reason, if the winget client is not on your PATH, it will be bundled with the app installer package from the Microsoft store. Updating this component should also install command line tools.

(NOTE: installation commands if not issued from a shell with Administrator privileges, UAC prompts will pop up. If you are in an automated scenario where that’s an issue, make sure to work in such a shell.)

(Note: If the install command is not issued from a shell with administrator privileges, a UAC prompt will pop up. If you are in an automation scenario where the problem occurs, make sure to work in such a shell.)

After installing everything, open a new shell, otherwise the tools will not be available on the PATH for convenient invocation.

Once everything is installed, open a new shell, otherwise the tools won’t be easily accessible on the PATH.

C/C++ compiler

C/C++ Compiler

Open your favorite shell in your favorite terminal and issue:

Open your favorite shell in your favorite terminal and issue:

winget install "Visual Studio Build Tools 2022"
Command-line component selection
Command line component selection

In automated scenarios with no GUI available, please consult the VS docs on specifying the required workloads. A minimal configuration which may be imported using the GUI or specfied on the command-line is as:

?In automation scenarios where no GUI is available, refer to the VS documentation to specify the required workload. The minimal configuration that can be imported using the GUI or specified on the command line is as follows:

 & amp; "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" install --passive --norestart --productId Microsoft.VisualStudio.Product.BuildTools --channelId VisualStudio.17. Release --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest

Developers targeting Windows 10 will need to add --add Microsoft.VisualStudio.Component.Windows10SDK.19041 to the command-line while targeting Windows 11 requires --add Microsoft.VisualStudio.Component.Windows11SDK .22000

Developers targeting Windows 10 need to add --add Microsoft.VisualStudio.Component.Windows10SDK.19041 to the command line, while developers targeting Windows 11 need to add --add Microsoft.VisualStudio Component.Windows11SDK.22000

Git

You most likely already have Git installed. If not, we’ll install it, because this is what Vcpkg uses to keep it’s repository up-to-date. Open your favorite shell in your faovrite terminal and issue:

Most likely you already have Git installed. If not, we will install it as this is what Vcpkg uses to keep its repository up to date. Open your favorite shell in your faovrite terminal and issue:

winget install Git.Git

CMake

If you do not have CMake installed yet, we’ll install it, as it’s the primary supported build system, as it will make our builds much simpler. Open your favorite shell in your faovrite terminal and issue:

If you don’t have CMake installed yet, we will install it since it is the main supported build system and because it will make our builds much simpler. Open your favorite shell in your faovrite terminal and issue:

winget install Kitware.CMake

Visual Studio Code

While IDEs are highly opinionated, for an IDE with widespread adoption and small footprint, VS Code has everything (and more) to get off the ground.

While IDEs are very opinionated, for a widely adopted IDE with a small footprint, VS Code has everything (and more) you need to get started.

winget install "Visual Studio Code" --source msstore

OpenCL-SDK

To build native OpenCL applications, one will minimally need:

To build a native OpenCL application, you minimally need:

  • C or C++ compiler
  • C or C++ compiler
  • The OpenCL headers
  • OpenCL header file
    • The C and optionally the C++ headers
    • C and optional C++ header files
  • An Installable Client Driver (ICD) Loader
  • Installable client driver (ICD) loader
    • Dynamic library (OpenCL.dll)
    • Dynamic library (OpenCL.dll)
    • Export library (OpenCL.lib)
    • Export library (OpenCL.lib)

The SDK can be installed from a package manager like Vcpkg or can be built on-demand from their canonical repositories.

The SDK can be installed from a package manager like Vcpkg or built on demand from their canonical repository.

GitHub

If you want to build an SDK from source, the recommended way is cloning the OpenCL-SDK repo.

If you want to build the SDK from source, the recommended method is to clone the OpenCL SDK repo.

git clone --recursive https://github.com/KhronosGroup/OpenCL-SDK.git
cmake -G "Visual Studio 17 2022" -A x64 -T v143 -D CMAKE_INSTALL_PREFIX=./OpenCL-SDK/install -B ./OpenCL-SDK/build -S ./OpenCL-SDK
cmake --build OpenCL-SDK/build --config Release --target install -- /m /v:minimal

Vcpkg

Compiling on the command-line

Compile on the command line

On Windows the default system command interpreter is cmd.exe. (This is analogous to /bin/sh in Linux.) The default shell however is PowerShell which provides better user- experience overall. (Much like Linux defaults to /bin/bash.) PowerShell provides a better CLI experience overall.

On Windows, the default system command interpreter is cmd.exe. (This is similar to /bin/sh in Linux.) However, the default shell is PowerShell, which provides a better user experience overall. (Very similar to the Linux default /bin/bash.) PowerShell provides a better CLI experience overall.

Invoking the compiler manually

Manually call the compiler

Unlike compilers native to *nix OS flavors, MSVC relies on a few environmental variables to function properly. Such environments are referred to as Developer Command Prompt or Developer PowerShell, which are nothing more than ordinary shells with these environmental variables setup.)

Unlike *nix OS-style native compilers, MSVC relies on some environment variables to work properly. Such environments are called Developer Command Prompt or Developer PowerShell, and they are nothing more than regular shells with these environment variables set. )

Developer Command Prompt
Developer Command Prompt

To build applications on the command-line using cmd.exe on Windows, one needs to open a Developer Command Prompt for VS 2022. This can be done in the Start Menu or by invoking vcvarsall.bat from the installation folder.

To build an application on the command line using cmd.exe on Windows, you need to open the developer command prompt of VS 2022. This can be done from the Start menu or by calling vcvarsall.bat from the installation folder.

"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64

(Note: for all combinations of available host-target toolset variables, consult vcvarsall.bat help)

(Note: See vcvarsall.bat help for all combinations of available host target toolset variables)

Developer PowerShell
Developer PowerShell

Inheriting environments set up by batch scripts is not trivial, hence VS provides a PowerShell module doing the same thing. The module is inside an assembly shipping with VS. To have the utility available in all shells, invoke the following from PowerShell:

Inheriting the environment set by a batch script is not trivial, so VS provides a PowerShell module to do the same thing. This module is in the assembly provided with VS. To make the utility available in all shells, call the following command from PowerShell:

if (-not (Test-Path ~\Documents\PowerShell)) { New-Item -Type Directory ~\Documents\PowerShell }
'Import-Module "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"' >> $PROFILE
function devshell { Enter-VsDevShell -InstallPath "C:\Kellekek\Microsoft\VisualStudio\2019\BuildTools" -SkipAutomaticLocation -DevCmdArguments "-arch=x64 -no_logo" }

Opening a new shell, one now can enter a Developer PowerShell by issuing:

Open a new shell and now enter Developer PowerShell by issuing the following command:

devshell -VsInstallPath 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools' -DevCmdArguments '-arch=x64 -no_logo'

Inside a Developer Command Prompt navigate to the folder where you wish to build your application. Our application will have a single Main.c source file:

Navigate to the folder where you want to build the application in the developer command prompt. Our application will have a Main.c source file:

// C standard includes
#include <stdio.h>

// OpenCL includes
#include <CL/cl.h>

int main()
{
    cl_int CL_err = CL_SUCCESS;
    cl_uint numPlatforms = 0;

    CL_err = clGetPlatformIDs( 0, NULL, & amp;numPlatforms );

    if (CL_err == CL_SUCCESS)
        printf_s("%u platform(s) found\
", numPlatforms);
    else
        printf_s("clGetPlatformIDs(%i)\
", CL_err);

    return 0;
}

Then invoke the compiler to build our source file as such:

The compiler is then invoked to build our source files like this:

GitHub

cl.exe /nologo /TC /W4 /DCL_TARGET_OPENCL_VERSION=100 /I<SDKINSTALLROOT>\include\ Main.c /Fe:HelloOpenCL /link /LIBPATH:<SDKINSTALLROOT>\lib OpenCL.lib

Vcpkg

What do the command-line arguments mean?

What do command line parameters mean?

  • /nologo makes the compiler omit printing a banner to the console
  • /nologo causes the compiler to omit printing a banner to the console
  • /TC tells it to treat all source files as C
  • /TC tells to treat all source files as C
  • /W4 turns on Warning level 4 (highest sensible level)
  • /W4 turns on warning level 4 (the highest perceptible level)
  • /D instructs the preprocessor to create a define with NAME:VALUE
  • /D instructs the preprocessor to create a definition using NAME:VALUE
    • CL_TARGET_OPENCL_VERSION enables/disables API functions corresponding to the defined version. Setting it to 100 will disable all API functions in the header that are newer than OpenCL 1.0
    • CL_TARGET_OPENCL_VERSION enables/disables API functions corresponding to the defined version. Setting it to 100 will disable all API functions in the header newer than OpenCL 1.0
  • /I sets additional paths to the include directory search paths
  • /I Set other paths to include directory search paths
  • Main.c is the name of the input source file
  • Main.c is the name of the input source file
  • /Fe: sets the name of the output executable (default would be Main.exe)
  • /Fe: Set the name of the output executable file (default is Main.exe)
  • /link allows passing arguments to the linker invoked by the compiler driver (flags of the compiler should not follow this argument)
  • /link allows arguments to be passed to the linker called by the compiler driver (the compiler’s flags should not follow this argument)
  • /LIBPATH sets additional paths to the library directory search paths
  • /LIBPATH sets another path for the library directory search path
  • OpenCL.lib is the vendor neutral ICD loader to link to
  • OpenCL.lib is a vendor-neutral ICD loader that can be linked to

Running our executable HelloOpenCL.exe either prints the number of platforms found or an error code which is often the result of corrupted runtime installations.

Running our executable HelloOpenCL.exe will print the number of platforms found or an error code, which is usually the result of a corrupt installation at runtime.

Automating the build using CMake

Use CMake to implement build automation

The CMake build script for this application that builds it as an ISO C11 app with most sensible compiler warnings turned on looks like:

The application’s CMake build script builds it as an ISO C11 application with the most sensible compiler warnings turned on, and looks like this:

cmake_minimum_required(VERSION 3.1) # 3.1 << C_STANDARD 11

project(HelloOpenCL LANGUAGES C)

find_package(OpenCL CONFIG REQUIRED)

add_executable(${PROJECT_NAME} Main.c)

target_link_libraries(${PROJECT_NAME} PRIVATE OpenCL::OpenCL)

set_target_properties(${PROJECT_NAME} PROPERTIES C_STANDARD 11
                                                 C_STANDARD_REQUIRED ON
                                                 C_EXTENSIONS OFF)

target_compile_definitions(${PROJECT_NAME} PRIVATE CL_TARGET_OPENCL_VERSION=100)

What does the script do?

What does this script do?

  • Give a name to the project and tell CMake to only look for a C compiler (default is to search for a C and a C++ compiler)
  • Give the project a name and tell CMake to only look for C compilers (by default it searches C and C++ compilers)
  • Look for an OpenCL SDK and fail if not found
  • Look for OpenCL SDK, fail if not found
    • If detection fails, refer to the CMake Build-System Support chapter.
    • ?If detection fails, see the CMake Build System Support chapter.
  • Specify our source files and name the executable
  • Specify our source file and name the executable
  • Specify dependency to the SDK (not just linkage)
  • Specify dependencies on SDK (not just links)
  • Set language properties to all source files of our application
  • Set the language attribute for all source files of the application
  • Set the OpenCL version target to control API coverage in header
  • Set OpenCL version target to control API coverage in headers
  • Because CMake cannot handle warning levels portably, set compiler specific flags. Guard it with a generator expression (terse conditionals), so other compilers will not pick up such non-portable flags.
  • Since CMake cannot handle warning levels portablely, set compiler-specific flags. Protect it with a generator expression (succinct conditional) so other compilers don’t pick up this non-portable flag.

To invoke this script, place it next to our Main.c file in a file called CMakeLists.txt. Once that’s done, cmake may be invoked the following way to generate Ninja makefiles in the advised out-of-source fashion into a subfolder named build:

To call this script, place it next to the Main.c file in a file called CMakeLists.txt. Once completed, cmake can be invoked to generate the Ninja makefile into a subfolder named build in the recommended out-of-source manner:

GitHub

cmake -A x64 -S . -B .\build -D CMAKE_PREFIX_PATH=<SDKINSTALLROOT>

Vcpkg

Which will output something like

It will output the following

-- The C compiler identification is MSVC 19.22.27905.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio620226BuildTools/VC/Tools/MSVC/14.22.27905/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio620226BuildTools/VC/Tools/MSVC/14.22.27905/bin/Hostx64/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for CL_VERSION_2_2
-- Looking for CL_VERSION_2_2 - found
-- Found OpenCL: C:/Users/mnagy/Source/Repos/vcpkg/installed/x64-windows/debug/lib/OpenCL.lib (found version "2.2")
-- Looking for pthread.h
-- Looking for pthread.h - not found
-- Found Threads: TRUE
--Configuring done
-- Generating done
-- Build files have been written to: C:/Users/mnagy/Source/CL-Min1/build

To kick off the build, one may use CMakes build driver:

To start the build, you can use the CMakes build driver:

cmake --build .\build --config Release

Once build is complete, we can run it by typing:

Once the build is complete, we can run it by typing:

.\build\Release\HelloOpenCL.exe