Queue
A queue provides the ability to describe the order in which tasks such as kernel, memory operations, etc. are executed.
If you are familiar with CUDA/HIP, a queue is comparable to a Stream.
Everything that is placed in a queue is executed according to the FIFO principle (first in, first out).
Different queues may run independently.
There are two types of queues: non-blocking and blocking queues.
If a task is placed in a non-blocking queue with the enqueue() call, the calling host thread does not wait until the task is started.
It is not defined whether the queued task is started immediately or with a delay.
If you need to access data that has been modified by your tasks, you need explicit synchronization barriers such as alpaka::onHost::wait(queue).
Alternatively, the data can be accessed within a task that is in the same queue.
Blocking means that the calling host thread waits until the previously queued task has been completed.
The use of the same queue by different host threads is supported.
A queue is a handle.
When the last copy of the handle leaves the scope, it is deleted.
The deletion is deferred until all tasks queued in the queue are completed.
Here is a small example for a blocking queue:
// Creating a blocking queue onHost::Queue queue = device.makeQueue(queueKind::blocking); uint32_t value = 42u; queue.enqueueHostFn([&value]() { value = 23u; }); // no wait required, enqueue will wait until the task is finished CHECK(value == 23u);
The use of a non-blocking queue requires explicit synchronization before accessing the modified data, otherwise a data race will occur.
If you do not pass queueKind as an argument, you will get a non-blocking queue.
// Creating a non-blocking queue onHost::Queue queue = device.makeQueue(queueKind::nonBlocking); uint32_t value = 42u; queue.enqueueHostFn([&value]() { value = 23; }); onHost::wait(queue); CHECK(value == 23u);
We will learn more about queue functions in later chapters.
Complete Source File
030_queue.cpp
1/* Copyright 2025 René Widera
2 * SPDX-License-Identifier: ISC
3 */
4
5#include "docsTest.hpp"
6
7#include <alpaka/alpaka.hpp>
8
9#include <catch2/catch_template_test_macros.hpp>
10#include <catch2/catch_test_macros.hpp>
11
12#include <cstdint>
13
14using namespace alpaka;
15
16TEMPLATE_LIST_TEST_CASE("non blocking queue", "[docs]", docs::test::TestBackends)
17{
18 auto selector = onHost::makeDeviceSelector(TestType::makeDict());
19 if(!selector.isAvailable())
20 return;
21 onHost::concepts::Device auto device = selector.makeDevice(0);
22
23 // Creating a non-blocking queue
24 onHost::Queue queue = device.makeQueue(queueKind::nonBlocking);
25 uint32_t value = 42u;
26 queue.enqueueHostFn([&value]() { value = 23; });
27 onHost::wait(queue);
28 CHECK(value == 23u);
29}
30
31TEMPLATE_LIST_TEST_CASE("blocking queue", "[docs]", docs::test::TestBackends)
32{
33 auto selector = onHost::makeDeviceSelector(TestType::makeDict());
34 if(!selector.isAvailable())
35 return;
36 onHost::concepts::Device auto device = selector.makeDevice(0);
37
38 // Creating a blocking queue
39 onHost::Queue queue = device.makeQueue(queueKind::blocking);
40 uint32_t value = 42u;
41 queue.enqueueHostFn([&value]() { value = 23u; });
42 // no wait required, enqueue will wait until the task is finished
43 CHECK(value == 23u);
44}