## Learning Objectives
* Learn about the SYCL system topology and how to traverse it
* Learn how to query information about a platform or device
* Learn how to select a device; both manually and using device selectors
#### SYCL System Topology
* A SYCL application can execute work across a range of different heterogeneous devices.
* The devices that are available in any given system are determined at runtime through topology discovery.
#### Platforms and devices
* The SYCL runtime will discover a set of platforms that are available in the system.
* Each platform represents a backend implementation such as Intel OpenCL or Nvidia PTX.
* The SYCL runtime will also discover all the devices available for each of those platforms.
* CPU, GPU, FPGA, and other kinds of accelerators.
![SYCL](../common-revealjs/images/devices-1.png "SYCL-Devices")
#### Platform and device classes
* Platforms and devices are represented by the `platform` and `device` classes respectively.
![SYCL](../common-revealjs/images/devices-1.png "SYCL-Devices")
#### Querying the topology
* In SYCL there are two ways to query a system’s topology.
* The topology can be manually queried and iterated over via APIs of the platform and device classes .
* The topology can be automatically queried and iterated over using a use specified heuristic by a device selector object.
#### Querying manually
auto platforms = platform::get_platforms();
![SYCL](../common-revealjs/images/devices-5.png "SYCL-Devices")
* The platform class provides the static function `get_platforms`.
* It retrieves a vector of all available platforms in the system.
#### Querying manually
auto intelDevices = intelPlatform.get_devices();
![SYCL](../common-revealjs/images/devices-6.png "SYCL-Devices")
* The platform class provides the member function
`get_devices` that returns a vector of all devices
associated with that platform.
#### Querying manually
auto devices = device::get_devices();
![SYCL](../common-revealjs/images/devices-7.png "SYCL-Devices")
* The device class also provides the static
function `get_devices` that returns a vector of all
available devices in the system.
#### Querying with a device selector
![Device Topology](../common-revealjs/images/topology-1.png "Device-Topology")
* To simplify the process of traversing the system topology SYCL provides device selectors.
* A device selector is is a callable C++ object which defines a heuristic for scoring devices.
* SYCL provides a number of standard device selectors, e.g. `default_selector_v`, `gpu_selector_v`, etc.
* Users can also create their own device selectors.
#### Querying with a device selector
auto gpuDevice = device(gpu_selector_v);
![Device Topology](../common-revealjs/images/topology-1.png "Device-Topology")
* A device selector takes a parameter of type `const device &` and gives it a "score".
* Used to query all devices and return the one with the highest "score".
* A device with a negative score will never be chosen.
#### Querying the topology using a device selector
auto chosenDevice = device();
auto chosenDevice = device(default_selector_v);
![Device Topology](../common-revealjs/images/topology-1.png "Device-Topology")
* The `default_selector_v` is a standard device selector.
* Chooses a device based on an implementation defined heuristic.
* A default constructed device or platform will use this selector.
#### Creating a custom device selector
int my_gpu_selector(const device& dev) {
}
* A device selector can be any callable object.
* A device selector must have a function call operator which takes a reference to a device.
#### Creating a custom device selector
int my_gpu_selector(const device& dev) {
if (dev.is_gpu()){
return 1;
}
else {
return -1;
}
}
* The body of the function call operator defines the heuristic for selecting devices
* This is where you write the logic for scoring each device
#### Creating a custom device selector
int my_gpu_selector(const device& dev) {
if (dev.is_gpu()){
return 1;
}
else {
return -1;
}
}
int main(int argc, char *argv[]) {
auto gpuQueue = queue{my_gpu_selector};
}
* Now that there is a device selector that chooses a specific device we can use that to construct a queue.
#### Platform/device info
auto plt = dev.get_platform();
auto platformName
= dev.get_info<info::device::name>();
![SYCL](../common-revealjs/images/topology-2.png "SYCL-Devices")
* Information about platforms and devices can be queried using the template member function `get_info`.
* The info that you are querying is specified by the template parameter.
* You can also query a device for its associated platform with the `get_platform` member function.
#### Aspects
bool supportsFp16 = dev.has(aspect::fp16);
* Capabilities of a device or platform are
represented by aspects.
* These can be queried via the `has` member
function.
#### Exercise
Code_Exercises/Device_Discovery/source
Create your own device selector that chooses the device in your system that you would like to target.