fairness
v1.0.0
A collection of advanced syncronization mechanisms.
|
This is not currently part of the Boost library collection.
However, my intention is to submit it for review once it's fully completed.
A collection of advanced syncronization mechanisms which are able to prioritize threads based on their priority, granting higher-priority threads access to protected resources ahead of lower-priority ones.
Designed to enhance throughput in pipelines by prioritizing slower threads.
The reason I started this library is that the operating system makes decisions regarding scheduling policies without knowledge of the application layer. Sometimes, a programmer optimizing an application may want to prioritize certain threads for various reasons.
When I started this library, I believed it would be relatively easy, but it turned out not to be. Throughout my study and development of this library, I realized that in this field, there are no "silver bullets" and each solution has its own set of pros and cons. Unable to find a universal solution for every architecture, I opted to allow users to customize certain critical aspects of the library. I recommend users of this library to read this page.
The standard library provides tools for handling concurrency but lacks effective ways to allow programmers to choose fairness policies.
Modifying these behaviors can be tricky, and mistakes may lead to issues such as thread starvation. If not used carefully, these tools can do more harm than good, emphasizing the importance of cautious usage.
Furthermore, the advanced synchronization mechanisms in this library do not automatically adjust priorities. This poses a risk of thread starvation when new threads are consistently created with high-priority locks.
Although priority-based locks are primarily designed to mitigate the issue of starvation and prevent it, they can also serve as a valuable tool in scenarios where traditional, non-priority-based synchronization mechanisms fall short. Here are some scenarios where a priority-based synchronization mechanism may be the preferred choice:
Real-time Systems: In real-time systems, tasks have strict timing requirements. Priority-based synchronization could be used that high-priority tasks are executed without delay, allowing critical functions like safety-critical control systems or healthcare devices to meet their deadlines.
Resource Allocation: In resource allocation scenarios where different processes or threads compete for resources (e.g., memory, CPU time), a priority-based mechanism can allocate resources to high-priority tasks, could be used to ensure that get the resources they need promptly.
Multi-Threaded Gaming: In multi-threaded gaming engines, priority-based synchronization can prioritize slower threads in order to increase throughput of the graphical pipeline so to increase FPS.
Scientific Simulations: Scientific simulations involve complex pipelines where maximizing throughput is crucial. Concurrent execution of multiple tasks in simulations makes priority-based synchronization effective for fine-tuning fairness policies and optimizing throughput.
In these use-cases, priority-based synchronization mechanisms enhance resource management, responsiveness, and prioritization of critical tasks, thereby improving system efficiency and performance in situations where fairness and timing are critical.
Additionally, managing fairness policies helps optimize around issues like priority inversion.
The primary intention behind creating these syncronization mechanisms is for their utilization within completed pipelines. In this context, the risk of thread starvation is non-existent due to the established pipeline structure.
The assumptions are:
These two images depict the same pipeline. The first image illustrates the execution of the pipeline with a mostly FIFO lock, while the second image demonstrates an improved execution using a priority lock. The priority lock could be employed to reduce the overall execution time of the pipeline.
I build and tested this lib with C++20.
If for some reason, on some compilers (not MinGW), it doesn`t work on C++20+ please email me or open an issue.
Download https://www.boost.org/users/history/version_1_82_0.html
In the directory where you want to put the Boost installation, execute:
Generate ninja build files and build:
Using cmake you can include this library as follows:
At this point you should be able to link the library simply using:
To run this code snippet, you should integrate the 'BS_thread_pool' library into your CMakeLists.txt by including it as follows:
Organize your directory structure as follows:
Now this snippet is ready-to-use.
The output of the above could be:
This is a list of macros that can be defined to configure boost::fairness:
MACRO | Default | Description |
---|---|---|
BOOST_FAIRNESS_WAIT_SPINS | 16 | The total number of spins before a syscall to the OS to yield the cpu through futex on linux or waitOnAdress on windows (this is used only if BOOST_FAIRNESS_USE_EXPERIMENTAL_WAIT_NOTIFY is defined). |
BOOST_FAIRNESS_WAIT_SPINS_RELAXED | 12 | The number of paused spins before a syscall to the OS to yield the cpu through futex on linux or waitOnAdress on windows (this is used only if BOOST_FAIRNESS_USE_EXPERIMENTAL_WAIT_NOTIFY is defined). |
BOOST_FAIRNESS_USE_TATAS | not defined | If defined contention will be solved with a simple tatas-based algorithm witch is faster but doesn't scale. |
BOOST_FAIRNESS_SPINWAIT_SPINS | 16 | The total number of spins performed while spin waiting. |
BOOST_FAIRNESS_SPINWAIT_SPINS_RELAXED | 12 | The number of paused spins performed while spin waiting. |
BOOST_FAIRNESS_HARDWARE_DESTRUCTIVE_SIZE | 128 | Hardware destructive size used by this library. |
BOOST_FAIRNESS_MAX_PQNODES | 4 | The number of requests each priority mutex has available (this is used only if BOOST_FAIRNESS_USE_TATAS is not defined). |
BOOST_FAIRNESS_MAX_THREADS | 4 | The total number of thread structs each thread has available (this is used only if BOOST_FAIRNESS_USE_TATAS is not defined). |
BOOST_FAIRNESS_USE_EXPERIMENTAL_WAIT_NOTIFY | not defined | Use a custom implementation to perform atomic::wait and atomic::notify instead of the standard ones. |
BOOST_FAIRNESS_GETREQUEST_SPINS | 1 | The total number of spins performed while performing a getRequest (this is used only if BOOST_FAIRNESS_USE_TATAS is not defined). |
BOOST_FAIRNESS_GETREQUEST_SPINS_RELAXED | 1 | The number of paused spins performed while performing a getRequest (this is used only if BOOST_FAIRNESS_USE_TATAS is not defined). |
If you encounter any issues or would like to suggest new features, please don't hesitate to open an issue or get in touch with me at feder.nosp@m.igno.nosp@m.li@ho.nosp@m.tmai.nosp@m.l.it.
Contributions are also welcome! Feel free to open pull requests to the main repository and assign me as a reviewer – I'll be sure to review them. Your help is greatly appreciated!
Distributed under the Boost Software License - Version 1.0. See LICENSE for more information.
The documentation is available at the following link: https://sernior.github.io/fairness/
Federico Abrignani - feder.nosp@m.igno.nosp@m.li@ho.nosp@m.tmai.nosp@m.l.it
Salvatore Martorana - salva.nosp@m.tore.nosp@m.marto.nosp@m.rana.nosp@m.@hotm.nosp@m.ail..nosp@m.com