![]() |
y-cruncher Multi-Precision Library |
![]() |
A Multi-threaded Multi-Precision Arithmetic Library(Powered by y-cruncher) |
(Last updated: February 19, 2017)
Shortcuts:
YMP Library:
Large Number Objects:
Low-Level Programming:
Multi-Threading and Parallelism
In the multicore era, it's parallelize or be left behind. It's really that simple. This page lists all the functionality related to parallelism.
Parallelism in y-cruncher and YMP is done using standard parallel constructs that are powered by a global framework.
This approaches emphasizes a separation of concerns where:
For historical reasons, y-cruncher project does not "natively" use any existing frameworks such as TBB or Cilk Plus. Instead, it
has an additional layer of abstraction that allows the framework to be configurable.
YMP supports the same set of frameworks as y-cruncher. As of YMP 1.1/y-cruncher v0.7.1, the list is:
Generally speaking, it is a bad idea to mix frameworks within the same application. While YMP allows this and provides an API for it, misusing the feature can easily lead to oversubscription and other problems.
General Guidelines:
Parallel frameworks are represented as ParallelFramework objects. This class is exposed as an incomplete type.
Compatibility with PublicLibs/Concurrency:
The PublicLibs module has another concurrency library with the BasicParallelizer interface. But It is not recommended to use it with the YMP library. Nothing bad will happen as they will coexist without issues. But there's no point when you're already linking in YMP.
Internally, the ParallelFramework object is actually a subclass of the BasicParallelizer interface. The sole purpose of the BasicParallelizer interface and the entire PublicLibs/Concurrency directory is to allow the stand-alone repos (i.e. DigitViewer) to get some basic parallelism in a way that is internally compatible with y-cruncher.
The stripped down versions that appear on GitHub will use one of the frameworks in the PublicLibs/Concurrency directory. But internally within y-cruncher, they will get one of the heavy-weight ParallelFramework objects.
The ParallelFramework object is currently a simple subclass of the BasicParallelizer with zero offset. So it is sometimes possible to reinterpret_cast a ParallelFramework into a BasicParallelizer and have it work correctly. However, this will only work if the vtables are compatible. Since vtable layout is not specified in the Windows ABI, this behavior is not officially supported.
It is not possible to pass a custom BasicParallelizer implementation into YMP to use internally.
Run two Actions in Parallel:
void run_in_parallel(BasicAction& a0, BasicAction& a1);
void run_in_parallel(ParallelFramework& framework, BasicAction& a0, BasicAction& a1);
Description:
Run both actions a0 and a1 with index = 0 assuming that they are independent. The function will not return until both actions are completed.
Depending on the parallel framework, these actions may be run in parallel. It is safe to call this function recursively.
If no framework is specified, it will use the global instance.
Exception propagation is currently not defined. Most frameworks will simply terminate the program on an unhandled exception.
Run a Range of Actions in Parallel:
void run_in_parallel(BasicAction& action, upL_t si, upL_t ei);
void run_in_parallel(ParallelFramework& framework, BasicAction& action, upL_t si, upL_t ei);
Description:
Runs the specified action for all index parameters in the range [si, ei) assuming independence. The function will not return until all actions are completed.
Depending on the parallel framework, these actions may be run in parallel. It is safe to call this function recursively.
If no framework is specified, it will use the global instance.
Exception propagation is currently not defined. Most frameworks will simply terminate the program on an unhandled exception.
Performance Note:
Unlike parallel-for constructs from other parallel libraries, this one doesn't try to be smart about grouping iterations together.
What you write is what you get. If you tell it to run an action for a billion different indices, it will dispatch a billion actions which (depending on the framework) may result in a billion context switches and/or threads.
Action Object:
class BasicAction{
public:
virtual void run(upL_t index = 0) = 0;
};
Description:
The base class for a simple action that takes an optional index parameter. This class is non-copyable and non-movable.
Performance Note:
Invoking an action object is an expensive operation that may involve multiple memory allocations, context switches, or even the creation of a new thread.
Use standard parallel programming common sense. Avoid using action objects for very small tasks.
Parallel Framework Management:
Global Parallel Framework:
ParallelFramework& get_global_framework();
void set_parallel_framework(ParallelFramework& framework);
Description:
Gets and sets the parallel framework for the entire library.
This framework is a global value that is shared by all threads. Therefore, these functions are not thread-safe.
It is undefined behavior to call set_parallel_framework() concurrently with any other library function.
Get Framework Name:
const char* framework_get_name(const ParallelFramework& framework);
Description:
Get the name of the specified framework.
Construct Parallel Framework:
dll_uptr<ParallelFramework> make_framework_by_name(const char* name);
Description:
Get a framework object by name. The framework is returned via a DLL-safe smart-pointer that behaves the same as std::unique_ptr.
Note that this function returns a new instance of the framework. So it's possible to create multiple instances of the same framework. While some frameworks can indeed be instantiated multiple times, some are singletons by nature and all instances will share the same runtime.
Different systems have different sets of frameworks:
Framework Name Description Availability "none" Disable all parallelism and sequentialize all tasks.
All systems
"spawn" Spawn a new thread for every task.
All systems
"cppasync" Use C++11's std::async().
All systems
"pushpool" Use y-cruncher's custom thread pool.
All systems
"winpool" Use the built-in Windows thread pool.
Windows only
"cilk" Use Intel's Cilk Plus.
All Linux systems + Windows systems with 256-bit AVX.
More details about the parallel frameworks can be found here.