diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b5e8da36ac..caf80fff86 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,26 +1,26 @@ ### Description -_Add comprehensive description of proposed changes_ +_Add a comprehensive description of proposed changes_ Fixes # - _issue number(s) if exists_ -- [ ] - git commit message contains appropriate signed-off-by string _(see [CONTRIBUTING.md](https://github.com/oneapi-src/oneTBB/blob/master/CONTRIBUTING.md#pull-requests) for details)_ +- [ ] - git commit message contains an appropriate signed-off-by string _(see [CONTRIBUTING.md](https://github.com/oneapi-src/oneTBB/blob/master/CONTRIBUTING.md#pull-requests) for details)_ ### Type of change _Choose one or multiple, leave empty if none of the other choices apply_ -_Add respective label(s) to PR if you have permissions_ +_Add a respective label(s) to PR if you have permissions_ -- [ ] bug fix - _change which fixes an issue_ -- [ ] new feature - _change which adds functionality_ +- [ ] bug fix - _change that fixes an issue_ +- [ ] new feature - _change that adds functionality_ - [ ] tests - _change in tests_ - [ ] infrastructure - _change in infrastructure and CI_ - [ ] documentation - _documentation update_ ### Tests -- [ ] added - _required for new features and for some bug fixes_ +- [ ] added - _required for new features and some bug fixes_ - [ ] not needed ### Documentation diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 74063b7b9e..c8b437083a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,18 +38,21 @@ You can use issues to report a problem, make a feature request, or add comments You can find all [open oneTBB pull requests](https://github.com/oneapi-src/oneTBB/pulls) on GitHub. -No anonymous contributions are accepted. The name in the commit message Signed-of-by line and your email must match the change authorship information. Make sure your .gitconfig is set up correctly so you can use `git commit -s` for signing your patches: +No anonymous contributions are accepted. The name in the commit message Signed-off-by line and your email must match the change authorship information. Make sure your .gitconfig is set up correctly so you can use `git commit -s` for signing your patches: `git config --global user.name "Taylor Developer"` `git config --global user.email taylor.developer@company.com` - -Before contributing changes directly to the oneTBB repository: +### Before contributing changes directly to the oneTBB repository * Make sure you can build the product and run all the tests with your patch. * For a larger feature, provide a relevant test. * Document your code. The oneTBB project uses reStructuredText for documentation. +* Update the copyright year in the first line of the changing file(s). + For example, if you commit your changes in 2022: + * the copyright year should be `2005-2022` for existing files + * the copyright year should be `2022` for new files * Submit a pull request into the master branch. You can submit changes with a pull request (preferred) or by sending an email patch. Continuous Integration (CI) testing is enabled for the repository. Your pull request must pass all checks before it can be merged. We will review your contribution and may provide feedback to guide you if any additional fixes or modifications are necessary. When reviewed and accepted, your pull request will be merged into our GitHub repository. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 3f6f1c0686..6e7093059a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -18,17 +18,15 @@ This document contains changes of oneTBB compared to the last release. ## Table of Contents -- [Preview Features](#preview-features) - [New Features](#new_features) - [Known Limitations](#known-limitations) - [Fixed Issues](#fixed-issues) - - -## :computer: Preview Features -- Extended task_group interface with a new run_and_wait overload to accept task_handle. +- [Open-source Contributions Integrated](#open-source-contributions-integrated) ## :white_check_mark: New Features -- Enabled Microsoft Visual Studio* 2022 and Python 3.9 support. +- Improved support and use of the latest C++ standards for parallel_sort that allows using this algorithm with user-defined and standard library-defined objects with modern semantics. +- The following features are now fully functional: task_arena extensions, collaborative_call_once, adaptive mutexes, heterogeneous overloads for concurrent_hash_map, and task_scheduler_handle. +- Added support for Windows* Server 2022 and Python 3.10. ## :rotating_light: Known Limitations - An application using Parallel STL algorithms in libstdc++ versions 9 and 10 may fail to compile due to incompatible interface changes between earlier versions of Threading Building Blocks (TBB) and oneAPI Threading Building Blocks (oneTBB). Disable support for Parallel STL algorithms by defining PSTL_USE_PARALLEL_POLICIES (in libstdc++ 9) or _GLIBCXX_USE_TBB_PAR_BACKEND (in libstdc++ 10) macro to zero before inclusion of the first standard header file in each translation unit. @@ -41,7 +39,15 @@ This document contains changes of oneTBB compared to the last release. - C++ exception handling mechanism on Windows* OS on ARM64* might corrupt memory if an exception is thrown from any oneTBB parallel algorithm (see Windows* OS on ARM64* compiler issue: https://developercommunity.visualstudio.com/t/ARM64-incorrect-stack-unwinding-for-alig/1544293). ## :hammer: Fixed Issues -- Reworked synchronization mechanism to reduce contention when multiple task_arena's are used concurrently. -- Fixed possible correctness issue in queuing_rw_mutex on non-Intel platforms. -- Fixed GCC* 11 warnings. -- Fixed sporadic memory corruption. +- Memory allocator crash on a system with an incomplete /proc/meminfo (GitHub* [#584](https://github.com/oneapi-src/oneTBB/issues/584)). +- Incorrect blocking of task stealing (GitHub* #[478](https://github.com/oneapi-src/oneTBB/issues/478)). +- Hang due to incorrect decrement of a limiter_node (GitHub* [#634](https://github.com/oneapi-src/oneTBB/issues/634)). +- Memory corruption in some rare cases when passing big messages in a flow graph (GitHub* [#639](https://github.com/oneapi-src/oneTBB/issues/639)). +- Possible deadlock in a throwable flow graph node with a lightweight policy. The lightweight policy is now ignored for functors that can throw exceptions (GitHub* [#420](https://github.com/oneapi-src/oneTBB/issues/420)). +- Crash when obtaining a range from empty ordered and unordered containers (GitHub* [#641](https://github.com/oneapi-src/oneTBB/issues/641)). +- Deadlock in a concurrent_vector resize() that could happen when the new size is less than the previous size (GitHub* [#733](https://github.com/oneapi-src/oneTBB/issues/733)). + +## :octocat: Open-source Contributions Integrated +- Improved aligned memory allocation. Contributed by Andrey Semashev (https://github.com/oneapi-src/oneTBB/pull/671). +- Optimized usage of atomic_fence on IA-32 and Intel(R) 64 architectures. Contributed by Andrey Semashev (https://github.com/oneapi-src/oneTBB/pull/328). +- Fixed incorrect definition of the assignment operator in containers. Contributed by Andrey Semashev (https://github.com/oneapi-src/oneTBB/issues/372). diff --git a/doc/GSG/Images/how-oneTBB-works.png b/doc/GSG/Images/how-oneTBB-works.png new file mode 100644 index 0000000000..f72427a814 Binary files /dev/null and b/doc/GSG/Images/how-oneTBB-works.png differ diff --git a/doc/GSG/examples.rst b/doc/GSG/examples.rst new file mode 100644 index 0000000000..6fe719c68d --- /dev/null +++ b/doc/GSG/examples.rst @@ -0,0 +1,45 @@ +.. _examples: + +oneTBB Samples +============== + +Refer to the following examples to see how |short_name| works. + +* **Containers** + + * `concurrent_hash_map `_ + * `concurrent_priority_queue `_ + +* `Flow Graph `_ + * `A solution to the binpacking problem using a queue_node, a buffer_node, and function_node. `_ + * `Cholesky Factorization algorithm `_ + * `An implementation of dining philosophers in graph using the reserving join_node `_ + * `A parallel implementation of bzip2 block-sorting file compressor `_ + * `An example of a collection of digital logic gates that can be easily composed into larger circuits `_ + * `An example of a Kohonen Self-Organizing Map using cancellation `_ + * `Split computational kernel for execution between CPU and GPU `_ + +* **Algorithms** + + * `parallel_for `_ + * `Game of life overlay `_ + * `Polygon overlay `_ + * `Parallel seismic wave simulation `_ + * `Parallel 2-D raytracer/renderer `_ + * `Find largest matching substrings `_ + * `Resumable task: Split computational kernel for execution between CPU and GPU `_ + * `parallel_for_each `_ + * `parallel_pipeline `_ + * `parallel_reduce `_ + +* **Task Scheduler** + + * `task_arena `_ + * `task_group `_ + * `Execute similar computational kernels, with one task executing the SYCL* code and the other task executing the oneTBB code `_ + +* **Other** + + * `Compute Fibonacci numbers in different ways `_ + + diff --git a/doc/GSG/installation.rst b/doc/GSG/installation.rst new file mode 100644 index 0000000000..e6b6a09c34 --- /dev/null +++ b/doc/GSG/installation.rst @@ -0,0 +1,7 @@ +.. _installation: + +Installation +============ + +See the `installation instructions `_ +that will help you to install |short_name| successfully. \ No newline at end of file diff --git a/doc/GSG/intro_gsg.rst b/doc/GSG/intro_gsg.rst index dfef1897c4..49fda780f6 100644 --- a/doc/GSG/intro_gsg.rst +++ b/doc/GSG/intro_gsg.rst @@ -1,13 +1,23 @@ .. _Intro_gsg: -|short_name| is a runtime-based parallel programming model for C++ code that uses threads. -It enables you to simplify parallel programming by breaking -computation into parallel running tasks. -The library consists of a template-based runtime library to help you harness the latent performance -of multi-core processors. Use |short_name| to write scalable applications that: +|full_name| is a runtime-based parallel programming model for C++ code that uses threads. +It consists of a template-based runtime library to help you harness the latent performance of multi-core processors. +oneTBB enables you to simplify parallel programming by breaking computation into parallel running tasks. Within a single process, +parallelism is carried out through threads, an operating system mechanism that allows the same or different sets of instructions +to be executed simultaneously. -- Specify logical parallel structure instead of threads -- Emphasize data parallel programming -- Take advantage of concurrent collections and parallel algorithms +Here you can see one of the possible executions of tasks by threads. + +.. figure:: /GSG/Images/how-oneTBB-works.png + :scale: 70% + :align: center + +Use oneTBB to write scalable applications that: + +* Specify logical parallel structure instead of threads +* Emphasize data-parallel programming +* Take advantage of concurrent collections and parallel algorithms + +oneTBB supports nested parallelism and load balancing. It means that you can use the library without being worried about oversubscribing a system. diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000..3ac68fcfb6 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,36 @@ +#=============================================================================== +# Copyright (C) 2022 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#=============================================================================== + +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = doc +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000000..0cdd56f9c1 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,34 @@ +# How to build oneTBB documentation + +Our documentation is written in restructured text markup (.rst) and built using [Sphinx](http://www.sphinx-doc.org/en/master/). + +This document explains how to build oneTBB documentation locally. + +## Prerequisites +- Python 3.7.0 or higher +- Sphinx + +## Build documentation + +Do the following to generate HTML output of the documentation: + +1. Clone oneTBB repository: + +``` +git clone https://github.com/oneapi-src/oneTBB.git +``` + +2. Go to the `doc` folder: + +``` +cd oneTBB/doc +``` + +3. Run in the command line: + +``` +make html +``` + + +That's it! Your built documentation is located in the ``build/html`` folder. diff --git a/doc/conf.py b/doc/conf.py index 3cc3f403fe..4c7e2b8a4b 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -29,7 +29,7 @@ project = u'IntelĀ® oneAPI Threading Building Blocks (oneTBB)' else: project = u'oneTBB' -copyright = u'2021, Intel Corporation' +copyright = u'2022, Intel Corporation' author = u'Intel' # The short X.Y version @@ -60,7 +60,7 @@ ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ['main/_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: @@ -120,21 +120,26 @@ # further. For a list of options available for each theme, see the # documentation. # -if BUILD_TYPE == 'oneapi' or BUILD_TYPE == 'dita': - html_theme = 'sphinx_rtd_theme' + +html_theme = 'sphinx_book_theme' + +if BUILD_TYPE == 'dita': + html_theme_options = { + 'repository_url': 'https://github.com/oneapi-src/oneTBB', + 'path_to_docs': 'doc', + 'repository_branch': 'master' + } else: - html_theme = 'sphinx_book_theme' html_theme_options = { - 'repository_url': 'https://github.com/oneapi-src/oneTBB', - 'path_to_docs': 'doc/main', - 'use_issues_button': True, - 'use_edit_page_button': True, - 'repository_branch': 'master', - 'extra_footer': '

Cookies

' + 'repository_url': 'https://github.com/oneapi-src/oneTBB', + 'path_to_docs': 'doc/main', + 'use_issues_button': True, + 'use_edit_page_button': True, + 'repository_branch': 'master', + 'extra_footer': '

Cookies

' } - # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". @@ -148,8 +153,9 @@ } else: html_js_files = ['custom.js'] - html_logo = '_static/oneAPI-rgb-rev-100.png' + +html_logo = '_static/oneAPI-rgb-rev-100.png' html_favicon = '_static/favicons.png' # Custom sidebar templates, must be a dictionary that maps document names diff --git a/doc/index/index_intro.rst b/doc/index/index_intro.rst index b82c487997..72055fe8d3 100644 --- a/doc/index/index_intro.rst +++ b/doc/index/index_intro.rst @@ -2,3 +2,4 @@ This document contains information about |short_name|. It is a flexible performance library that let you break computation into parallel running tasks. + diff --git a/doc/index/toctree.rst b/doc/index/toctree.rst index 364d52aefc..60cfe1e362 100644 --- a/doc/index/toctree.rst +++ b/doc/index/toctree.rst @@ -1,13 +1,33 @@ .. _toctree: .. toctree:: + :caption: About + :maxdepth: 1 + + /main/intro/help_support + /main/intro/notation + /main/intro/intro_os + /main/intro/Benefits + + +.. toctree:: + :caption: Get Started :maxdepth: 2 - main/intro/help_support - main/intro/notation - main/intro/intro_os - main/intro/Benefits - GSG/get_started - main/tbb_userguide/title - main/reference/reference - main/intro/notices_and_disclaimers \ No newline at end of file + /GSG/get_started + /GSG/installation + /GSG/examples + + +.. toctree:: + :maxdepth: 3 + :caption: Developer Guide + + /main/tbb_userguide/title + + +.. toctree:: + :maxdepth: 3 + :caption: Developer Reference + + /main/reference/reference diff --git a/doc/main/_templates/layout.html b/doc/main/_templates/layout.html index 2629d21887..eedbf5b39d 100644 --- a/doc/main/_templates/layout.html +++ b/doc/main/_templates/layout.html @@ -6,10 +6,12 @@ var wapLocalCode = 'us-en'; // Dynamically set per localized site, see mapping table for values var wapSection = "oneapi-tbb"; // WAP team will give you a unique section for your site // Load TMS - (function () { - var url = 'https://www.intel.com/content/dam/www/global/wap/tms-loader.js'; // WAP file URL - var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = url; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); + if(document.location.href.contains("oneapi-src.github.io")){ + (function () { + var url = 'https://www.intel.com/content/dam/www/global/wap/tms-loader.js'; // WAP file URL + var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = url; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })(); + } {% endblock %} diff --git a/doc/main/intro/introducing_main_os.rst b/doc/main/intro/introducing_main_os.rst deleted file mode 100644 index 0d6a1be95f..0000000000 --- a/doc/main/intro/introducing_main_os.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. _introducing_main: - -Introduction -============ - - -|full_name| is a library that supports scalable parallel programming using -standard ISO C++ code. It does not require special languages or -compilers. It is designed to promote scalable data parallel programming. -Additionally, it fully supports nested parallelism, so you can build -larger parallel components from smaller parallel components. To use the -library, you specify tasks, not threads, and let the library map tasks -onto threads in an efficient manner. - - -Many of the library interfaces employ generic programming, in which -interfaces are defined by requirements on types and not specific types. -The C++ Standard Template Library (STL) is an example of generic -programming. Generic programming enables oneTBB to be flexible yet -efficient. The generic interfaces enable you to customize components to -your specific needs. - - -.. note:: - |full_name| requires C++11 standard compiler support. - - -The net result is that oneTBB enables you to specify parallelism far -more conveniently than using raw threads, and at the same time can -improve performance. \ No newline at end of file diff --git a/doc/main/reference/reference.rst b/doc/main/reference/reference.rst index 855c3a869a..8990508206 100644 --- a/doc/main/reference/reference.rst +++ b/doc/main/reference/reference.rst @@ -50,6 +50,4 @@ The key properties of a preview feature are: constraints_extensions info_namespace_extensions task_group_extensions - task_arena_extensions - this_task_arena_extensions custom_mutex_chmap diff --git a/doc/main/reference/task_arena_extensions.rst b/doc/main/reference/task_arena_extensions.rst deleted file mode 100644 index 8cde3b29c1..0000000000 --- a/doc/main/reference/task_arena_extensions.rst +++ /dev/null @@ -1,61 +0,0 @@ -.. _task_arena_extensions: - -task_arena extensions -===================== - -.. note:: - To enable these extensions, set the ``TBB_PREVIEW_TASK_GROUP_EXTENSIONS`` macro to 1. - -.. contents:: - :local: - :depth: 1 - -Description -*********** - -|full_name| implementation extends the `tbb::task_arena specification `_ -with an overload of ``enqueue`` method accepting ``task_handle``. - - -API -*** - -Header ------- - -.. code:: cpp - - #include - -Synopsis --------- - -.. code:: cpp - - namespace oneapi { - namespace tbb { - - class task_arena { - public: - void enqueue(task_handle&& h); - }; - - } // namespace tbb - } // namespace oneapi - -Member Functions ----------------- - -.. cpp:function:: void enqueue(task_handle&& h) - -Enqueues a task owned by ``h`` into the ``task_arena`` for procession. - -Behavior of this function is identical to generic version (``template void task_arena::enqueue(F&& f)``) except parameter type. - -.. note:: - ``h`` should not be empty to avoid undefined behavior. - -.. rubric:: See also - -* `oneapi::tbb::task_arena specification `_ -* :ref:`task_handle` diff --git a/doc/main/reference/task_group_extensions.rst b/doc/main/reference/task_group_extensions.rst index ea4a7437ef..c2be6acca6 100644 --- a/doc/main/reference/task_group_extensions.rst +++ b/doc/main/reference/task_group_extensions.rst @@ -15,8 +15,6 @@ Description |full_name| implementation extends the `tbb::task_group specification `_ with the following members: - - constructor that takes a custom ``tbb::task_group_context`` object as an argument - - methods to create and run deferred tasks with ``task_handle`` - requirements for a user-provided function object @@ -40,15 +38,15 @@ Synopsis class task_group { public: - task_group(task_group_context& context); - + + //only the requirements for the return type of function F are changed template task_handle defer(F&& f); - void run(task_handle&& h); - - task_group_status run_and_wait(task_handle&&); - + //only the requirements for the return type of function F are changed + template + task_group_status run_and_wait(const F& f); + //only the requirements for the return type of function F are changed template void run(F&& f); @@ -62,43 +60,19 @@ Synopsis Member Functions ---------------- -.. cpp:function:: task_group(task_group_context& context) - -Constructs an empty ``task_group``, which tasks are associated with the ``context``. - - .. cpp:function:: template task_handle defer(F&& f) -Creates a deferred task to compute ``f()`` and returns ``task_handle`` pointing to it. - -The task is not scheduled for execution until explicitly requested. For example, with the ``task_group::run`` method. -However, the task is still added into the ``task_group``, thus the ``task_group::wait`` method waits until the ``task_handle`` is either scheduled or destroyed. - -The ``F`` type must meet the `Function Objects` requirements described in the [function.objects] section of the ISO C++ Standard. - As an optimization hint, ``F`` might return a ``task_handle``, which task object can be executed next. .. note:: - The ``task_handle`` returned by the function must be created with ``*this`` ``task_group``. It means, with the one for which run method is called, otherwise it is an undefined behavior. - -**Returns:** ``task_handle`` object pointing to task to compute ``f()``. - - -.. cpp:function:: void run(task_handle&& h) - -Schedules the task object pointed by the ``h`` for execution. + The ``task_handle`` returned by the function must be created using ``*this`` ``task_group``. That is, the one for which the run method is called, otherwise it is undefined behavior. -.. caution:: If ``h`` is empty or ``*this`` is not the same ``task_group`` that ``h`` is created with, the behavior is undefined. +.. cpp:function:: template task_group_status run_and_wait(const F& f) +As an optimization hint, ``F`` might return a ``task_handle``, which task object can be executed next. -.. cpp:function:: task_group_status run_and_wait(task_handle&& h) - -Equivalent to ``{run(std::move(h)); return wait();}``. - -**Returns**: The status of ``task_group``. - -.. caution:: - If ``h`` is empty or ``*this`` is not the same ``task_group`` that ``h`` is created with, the behavior is undefined. +.. note:: + The ``task_handle`` returned by the function must be created using ``*this`` ``task_group``. That is, the one for which the run method is called, otherwise it is undefined behavior. .. cpp:function:: template void run(F&& f) diff --git a/doc/main/reference/task_group_extensions/task_handle.rst b/doc/main/reference/task_group_extensions/task_handle.rst deleted file mode 100644 index b9b576d430..0000000000 --- a/doc/main/reference/task_group_extensions/task_handle.rst +++ /dev/null @@ -1,101 +0,0 @@ -.. _task_handle: - -task_handle -=========== - -.. note:: To enable these extensions, set the ``TBB_PREVIEW_TASK_GROUP_EXTENSIONS`` macro to 1. - - -.. contents:: - :local: - :depth: 1 - -Description -*********** - -This class owns a deferred task object. - -API -*** - -Header ------- - -.. code:: cpp - - #include - -Synopsis --------- - -.. code:: cpp - - namespace oneapi { - namespace tbb { - - class task_handle { - public: - task_handle(); - task_handle(task_handle&& src); - - ~task_handle(); - - task_handle& operator=(task_handle&& src); - - explicit operator bool() const noexcept; - }; - - bool operator==(task_handle const& h, std::nullptr_t) noexcept; - bool operator==(std::nullptr_t, task_handle const& h) noexcept; - - bool operator!=(task_handle const& h, std::nullptr_t) noexcept; - bool operator!=(std::nullptr_t, task_handle const& h) noexcept; - - } // namespace tbb - } // namespace oneapi - -Member Functions ----------------- - -.. cpp:function:: task_handle() - -Creates an empty ``task_handle`` object. - -.. cpp:function:: task_handle(task_handle&& src) - -Constructs ``task_handle`` object with the content of ``src`` using move semantics. ``src`` is left in an empty state. - -.. cpp:function:: ~task_handle() - -Destroys the ``task_handle`` object and associated task if it exists. - -.. cpp:function:: task_handle& operator=(task_handle&& src) - -Replaces the content of ``task_handle`` object with the content of ``src`` using move semantics. ``src`` is left in an empty state. -The previously associated task object, if any, is destroyed before the assignment. - -**Returns:** Reference to ``*this``. - -.. cpp:function:: explicit operator bool() const noexcept - -Checks if ``*this`` has an associated task object. - -**Returns:** ``true`` if ``*this`` is not empty, ``false`` otherwise. - -Non-Member Functions --------------------- - -.. code:: cpp - - bool operator==(task_handle const& h, std::nullptr_t) noexcept - bool operator==(std::nullptr_t, task_handle const& h) noexcept - -**Returns**: ``true`` if ``h`` is empty, ``false`` otherwise. - -.. code:: cpp - - bool operator!=(task_handle const& h, std::nullptr_t) noexcept - bool operator!=(std::nullptr_t, task_handle const& h) noexcept - -**Returns**: ``true`` if ``h`` is not empty, ``false`` otherwise. - diff --git a/doc/main/reference/this_task_arena_extensions.rst b/doc/main/reference/this_task_arena_extensions.rst deleted file mode 100644 index ddd0c31439..0000000000 --- a/doc/main/reference/this_task_arena_extensions.rst +++ /dev/null @@ -1,71 +0,0 @@ -.. _this_task_arena_extensions: - -this_task_arena extensions -========================== - -.. note:: - To enable these extensions, set the ``TBB_PREVIEW_TASK_GROUP_EXTENSIONS`` macro to 1. - -.. contents:: - :local: - :depth: 1 - -Description -*********** - -|full_name| implementation extends the `tbb::this_task_arena specification `_ -with an overloaded ``enqueue`` function. - - -API -*** - -Header ------- - -.. code:: cpp - - #include - -Synopsis --------- - -.. code:: cpp - - namespace oneapi { - namespace tbb { - namespace this_task_arena { - void enqueue(task_handle&& h); - - template - void enqueue(F&& f) ; - } // namespace this_task_arena - } // namespace tbb - } // namespace oneapi - -Member Functions ----------------- - - -.. cpp:function:: template void enqueue(F&& f) - -Enqueues a task into the ``task_arena`` currently used by the calling thread to process the specified functor, then immediately returns. -The ``F`` type must meet the `Function Objects` requirements described in the [function.objects] section of the ISO C++ Standard. - -Behavior of this function is identical to ``template void task_arena::enqueue(F&& f)`` applied to ``task_arena`` object constructed with ``attach`` parameter. - -.. cpp:function:: void enqueue(task_handle&& h) - -Enqueues a task owned by ``h`` into the ``task_arena`` that is currently used by the calling thread. - -Behavior of this function is identical to generic version (``template void enqueue(F&& f)``) except the parameter type. - -.. note:: - ``h`` should not be empty to avoid undefined behavior. - - -.. rubric:: See also: - -* `oneapi::tbb::this_task_arena specification `_ -* `oneapi::tbb::task_arena specification `_ -* :ref:`task_handle` diff --git a/doc/main/tbb_userguide/Advanced_Topic_Other_Kinds_of_Iteration_Spaces.rst b/doc/main/tbb_userguide/Advanced_Topic_Other_Kinds_of_Iteration_Spaces.rst index e5d572c3e4..3352dd8d32 100644 --- a/doc/main/tbb_userguide/Advanced_Topic_Other_Kinds_of_Iteration_Spaces.rst +++ b/doc/main/tbb_userguide/Advanced_Topic_Other_Kinds_of_Iteration_Spaces.rst @@ -4,15 +4,13 @@ Advanced Topic: Other Kinds of Iteration Spaces =============================================== -The examples so far have used the class ``blocked_range`` to specify -ranges. This class is useful in many situations, but it does not fit -every situation. You can use |full_name| -to define your own iteration space objects. The object must specify how -it can be split into subspaces by providing a basic splitting -constructor, an optional proportional splitting constructor (accompanied -with a trait value that enables its usage), and two predicate methods. -If your class is called ``R``, the methods and constructors should be as -follows: +The examples so far have used the class ``blocked_range`` to specify ranges. +This class is useful in many situations, but it does not fit every situation. +You can use |full_name| to define your own iteration space objects. The object +must specify how it can be split into subspaces by providing a basic splitting +constructor, an optional proportional splitting constructor, and two predicate +methods. If your class is called ``R``, the methods and constructors should be +as follows: :: @@ -25,10 +23,8 @@ follows: bool is_divisible() const; // Splits r into subranges r and *this R( R& r, split ); - // Splits r into subranges r and *this in proportion p + // (optional) Splits r into subranges r and *this in proportion p R( R& r, proportional_split p ); - // Allows usage of proportional splitting constructor - static const bool is_splittable_in_proportion = true; ... }; @@ -60,9 +56,7 @@ constructor is optional and takes the second argument of type that return the values of the proportion. These values should be used to split ``r`` accordingly, so that the updated ``r`` corresponds to the left part of the proportion, and the constructed object corresponds to -the right part. The proportional splitting constructor will be used only -if the static constant ``is_splittable_in_proportion`` is defined in the -class and assigned the value of ``true``. +the right part. Both splitting constructors should guarantee that the updated ``r`` part diff --git a/doc/main/tbb_userguide/Flow_Graph_resource_tips.rst b/doc/main/tbb_userguide/Flow_Graph_resource_tips.rst index b202fc2275..27dd524c5b 100644 --- a/doc/main/tbb_userguide/Flow_Graph_resource_tips.rst +++ b/doc/main/tbb_userguide/Flow_Graph_resource_tips.rst @@ -14,4 +14,5 @@ in a flow graph. ../tbb_userguide/use_limiter_node ../tbb_userguide/use_concurrency_limits - ../tbb_userguide/create_token_based_system \ No newline at end of file + ../tbb_userguide/create_token_based_system + ../tbb_userguide/attach_flow_graph_to_arena \ No newline at end of file diff --git a/doc/main/tbb_userguide/How_Task_Scheduler_Works.rst b/doc/main/tbb_userguide/How_Task_Scheduler_Works.rst new file mode 100644 index 0000000000..5ad1670baa --- /dev/null +++ b/doc/main/tbb_userguide/How_Task_Scheduler_Works.rst @@ -0,0 +1,50 @@ +.. _How_Task_Scheduler_Works.rst: + +How Task Scheduler Works +======================== + + +While the task scheduler is not bound to any particular type of parallelism, +it was designed to work efficiently for fork-join parallelism with lots of forks. +This type of parallelism is typical for parallel algorithms such as `oneapi::tbb::parallel_for +`_. + +Let's consider the mapping of fork-join parallelism on the task scheduler in more detail. + +The scheduler runs tasks in a way that tries to achieve several targets simultaneously: + - Enable as many threads as possible, by creating enough job, to achieve actual parallelism + - Preserve data locality to make a single thread execution more efficient + - Minimize both memory demands and cross-thread communication to reduce an overhead + +To achieve this, a balance between depth-first and breadth-first execution strategies +must be reached. Assuming that the task graph is finite, depth-first is better for +a sequential execution because: + +- **Strike when the cache is hot**. The deepest tasks are the most recently created tasks and therefore are the hottest in the cache. + Also, if they can be completed, tasks that depend on it can continue executing, and though not the hottest in a cache, + they are still warmer than the older tasks deeper in the dequeue. + +- **Minimize space**. Execution of the shallowest task leads to the breadth-first unfolding of a graph. It creates an exponential + number of nodes that co-exist simultaneously. In contrast, depth-first execution creates the same number + of nodes, but only a linear number can exists at the same time, since it creates a stack of other ready + tasks. + +Each thread has its deque of tasks that are ready to run. When a +thread spawns a task, it pushes it onto the bottom of its deque. + +When a thread participates in the evaluation of tasks, it constantly executes +a task obtained by the first rule that applies from the roughly equivalent ruleset: + +- Get the task returned by the previous one, if any. + +- Take a task from the bottom of its deque, if any. + +- Steal a task from the top of another randomly chosen deque. If the + selected deque is empty, the thread tries again to execute this rule until it succeeds. + +Rule 1 is described in :doc:`Task Scheduler Bypass `. +The overall effect of rule 2 is to execute the *youngest* task spawned by the thread, +which causes the depth-first execution until the thread runs out of work. +Then rule 3 applies. It steals the *oldest* task spawned by another thread, +which causes temporary breadth-first execution that converts potential parallelism +into actual parallelism. diff --git a/doc/main/tbb_userguide/Migration_Guide/Task_API.rst b/doc/main/tbb_userguide/Migration_Guide/Task_API.rst index 08d66b5c82..cdf922a316 100644 --- a/doc/main/tbb_userguide/Migration_Guide/Task_API.rst +++ b/doc/main/tbb_userguide/Migration_Guide/Task_API.rst @@ -364,11 +364,10 @@ is not guaranteed to be executed next by the current thread. root.wait_for_all();; } -In oneTBB this can be done using the preview feature of ``oneapi::tbb::task_group``. +In oneTBB, this can be done using ``oneapi::tbb::task_group``. .. code:: cpp - #define TBB_PREVIEW_TASK_GROUP_EXTENSIONS 1 #include // Assuming OtherTask is defined. @@ -421,11 +420,10 @@ and waiting on it is implemented as follows: // i.e. after the callback is called } -In oneTBB this can be done using the preview feature of ``oneapi::tbb::task_group``. +In oneTBB, this can be done using ``oneapi::tbb::task_group``. .. code:: cpp - #define TBB_PREVIEW_TASK_GROUP_EXTENSIONS 1 #include int main(){ diff --git a/doc/main/tbb_userguide/Task_Scheduler_Bypass.rst b/doc/main/tbb_userguide/Task_Scheduler_Bypass.rst new file mode 100644 index 0000000000..c198f6ac6b --- /dev/null +++ b/doc/main/tbb_userguide/Task_Scheduler_Bypass.rst @@ -0,0 +1,20 @@ +.. _Task_Scheduler_Bypass: + +Task Scheduler Bypass +===================== + +Scheduler bypass is an optimization where you directly specify the next task to run. +According to the rules of execution described in :doc:`How Task Scheduler Works `, +the spawning of the new task to be executed by the current thread involves the next steps: + + - Push a new task onto the thread's deque. + - Continue to execute the current task until it is completed. + - Take a task from the thread's deque, unless it is stolen by another thread. + +Steps 1 and 3 introduce unnecessary deque operations or, even worse, allow stealing that can hurt +locality without adding significant parallelism. These problems can be avoided by using "Task Scheduler Bypass" technique to directly point the preferable task to be executed next +instead of spawning it. When, as described in :doc:`How Task Scheduler Works `, +the returned task becomes the first candidate for the next task to be executed by the thread. Furthermore, this approach almost guarantees that +the task is executed by the current thread and not by any other thread. + +Please note that at the moment the only way to use this optimization is to use `preview feature of ``onepai::tbb::task_group`` \ No newline at end of file diff --git a/doc/main/tbb_userguide/Task_Scheduler_Summary.rst b/doc/main/tbb_userguide/Task_Scheduler_Summary.rst deleted file mode 100644 index 7c77d8f9df..0000000000 --- a/doc/main/tbb_userguide/Task_Scheduler_Summary.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. _Task_Scheduler_Summary: - -Task Scheduler Summary -====================== - - -The task scheduler works most efficiently for fork-join parallelism with -lots of forks, so that the task-stealing can cause sufficient -breadth-first behavior to occupy threads, which then conduct themselves -in a depth-first manner until they need to steal more work. - diff --git a/doc/main/tbb_userguide/The_Task_Scheduler.rst b/doc/main/tbb_userguide/The_Task_Scheduler.rst index ac57e02037..d9e6056e1c 100644 --- a/doc/main/tbb_userguide/The_Task_Scheduler.rst +++ b/doc/main/tbb_userguide/The_Task_Scheduler.rst @@ -16,5 +16,6 @@ onto one of the high-level templates, use the task scheduler. ../tbb_userguide/Task-Based_Programming ../tbb_userguide/When_Task-Based_Programming_Is_Inappropriate - ../tbb_userguide/Task_Scheduler_Summary + ../tbb_userguide/How_Task_Scheduler_Works + ../tbb_userguide/Task_Scheduler_Bypass ../tbb_userguide/Guiding_Task_Scheduler_Execution \ No newline at end of file diff --git a/doc/main/tbb_userguide/attach_flow_graph_to_arena.rst b/doc/main/tbb_userguide/attach_flow_graph_to_arena.rst new file mode 100644 index 0000000000..d887d4b223 --- /dev/null +++ b/doc/main/tbb_userguide/attach_flow_graph_to_arena.rst @@ -0,0 +1,47 @@ +.. _attach_flow_graph_to_arena: + +Attach Flow Graph to an Arbitrary Task Arena +====================== + + +|short_name| ``task_arena`` interface provides mechanisms to guide tasks +execution within the arena by setting the preferred computation units, +restricting part of computation units, or limiting arena concurrency. In some +cases, you may want to apply such mechanisms when a flow graph executes. + +During its construction, a ``graph`` object attaches to the arena, in which the constructing +thread occupies a slot. + +This example shows how to set the most performant core type as the preferred one +for a graph execution: + + +.. literalinclude:: ./snippets/flow_graph_examples.cpp + :language: c++ + :start-after: /*begin_attach_to_arena_1*/ + :end-before: /*end_attach_to_arena_1*/ + + +A ``graph`` object can be reattached to a different ``task_arena`` by calling +the ``graph::reset()`` function. It reinitializes and reattaches the ``graph`` to +the task arena instance, inside which the ``graph::reset()`` method is executed. + +This example shows how to reattach existing graph to an arena with the most performant +core type as the preferred one for a work execution. Whenever a task is spawned on behalf +of the graph, it is spawned in the arena of a graph it is attached to, disregarding +the arena of the thread that the task is spawned from: + + +.. literalinclude:: ./snippets/flow_graph_examples.cpp + :language: c++ + :start-after: /*begin_attach_to_arena_2*/ + :end-before: /*end_attach_to_arena_2*/ + +See the following topics to learn more: + +.. toctree:: + :maxdepth: 4 + + ../tbb_userguide/Guiding_Task_Scheduler_Execution + ../tbb_userguide/work_isolation + diff --git a/doc/main/tbb_userguide/design_patterns/Design_Patterns.rst b/doc/main/tbb_userguide/design_patterns/Design_Patterns.rst index 48d04618db..5daa696b5b 100644 --- a/doc/main/tbb_userguide/design_patterns/Design_Patterns.rst +++ b/doc/main/tbb_userguide/design_patterns/Design_Patterns.rst @@ -51,6 +51,7 @@ expressions into equivalent C++03 code. ../../tbb_userguide/design_patterns/Divide_and_Conquer ../../tbb_userguide/design_patterns/GUI_Thread ../../tbb_userguide/design_patterns/Non-Preemptive_Priorities + ../../tbb_userguide/design_patterns/Lazy_Initialization ../../tbb_userguide/design_patterns/Local_Serializer ../../tbb_userguide/design_patterns/Fenced_Data_Transfer ../../tbb_userguide/design_patterns/Reference_Counting diff --git a/doc/main/tbb_userguide/design_patterns/Images/image008a.jpg b/doc/main/tbb_userguide/design_patterns/Images/image008a.jpg new file mode 100644 index 0000000000..f1199dbaef Binary files /dev/null and b/doc/main/tbb_userguide/design_patterns/Images/image008a.jpg differ diff --git a/doc/main/tbb_userguide/design_patterns/Images/image009a.jpg b/doc/main/tbb_userguide/design_patterns/Images/image009a.jpg new file mode 100644 index 0000000000..02cd196067 Binary files /dev/null and b/doc/main/tbb_userguide/design_patterns/Images/image009a.jpg differ diff --git a/doc/main/tbb_userguide/design_patterns/Lazy_Initialization.rst b/doc/main/tbb_userguide/design_patterns/Lazy_Initialization.rst new file mode 100644 index 0000000000..ccba0d2499 --- /dev/null +++ b/doc/main/tbb_userguide/design_patterns/Lazy_Initialization.rst @@ -0,0 +1,109 @@ +.. _Lazy_Initialization: + +Lazy Initialization +================== + + +.. container:: section + + + .. rubric:: Problem + :class: sectiontitle + + Delay the creation of an object, potentially expensive, until it is accessed. + In parallel programming, initialization must also be guarded against race conditions. + + +.. container:: section + + + .. rubric:: Context + :class: sectiontitle + + The cost of operations that take place during the initialization + of the object may be considerably high. In that case, the object + should be initialized only when needed. Lazy initialization is + the common tactic that allows implementing such an approach. + + +.. container:: section + + + .. rubric:: Solution + :class: sectiontitle + + Using ``oneapi::tbb::collaborative_call_once`` with ``oneapi::tbb::collaborative_once_flag`` + helps to implement thread-safe lazy initialization for a user object. + + + In addition, ``collaborative_call_once`` allows other thread blocked on + the same ``collaborative_once_flag`` to join other |short_name| + parallel constructions called within the initializing function. + + +.. container:: section + + + .. rubric:: Example + :class: sectiontitle + + This example illustrates the implementation of lazy initialization + for the calculation of the Fibonacci numbers. Here is a graphical + representation of the Fibonacci recursion tree for N=4. + + + |image0| + + + As seen in the diagram, some elements are recalculated more than once. These operations are redundant, + so the "lazy initialized" Fibonacci numbers are relevant here. + + + An implementation without the use of lazy initialization would have *O(2^N)* time complexity due to + the full recursion tree traversal and recalculation of values. Since all the nodes are traversed once, + the tree becomes a list, making the time complexity *O(N)*. + + + |image1| + + + Here you can see the code for the implementation. Already calculated values are stored in a buffer + paired with ``collaborative_once_flag`` and will not be recalculated when ``collaborative_call_once`` + is invoked when initialization has already been done. + + + :: + + + using FibBuffer = std::vector>; + + std::uint64_t LazyFibHelper(int n, FibBuffer& buffer) { + // Base case + if (n <= 1) { + return n; + } + // Calculate nth value only once and store it in the buffer. + // Other threads won't be blocked on already taken collaborative_once_flag + // but join parallelism inside functor + oneapi::tbb::collaborative_call_once(buffer[n].first, [&]() { + std::uint64_t a, b; + oneapi::tbb::parallel_invoke([&] { a = LazyFibHelper(n - 2, buffer); }, + [&] { b = LazyFibHelper(n - 1, buffer); }); + buffer[n].second = a + b; + }); + + return buffer[n].second; + } + + std::uint64_t Fib(int n) { + FibBuffer buffer(n+1); + return LazyFibHelper(n, buffer); + } + + +.. |image0| image:: Images/image008a.jpg + :width: 744px + :height: 367px +.. |image1| image:: Images/image009a.jpg + :width: 744px + :height: 367px diff --git a/doc/main/tbb_userguide/snippets/flow_graph_examples.cpp b/doc/main/tbb_userguide/snippets/flow_graph_examples.cpp new file mode 100644 index 0000000000..c1b97975c3 --- /dev/null +++ b/doc/main/tbb_userguide/snippets/flow_graph_examples.cpp @@ -0,0 +1,76 @@ +/* + Copyright (c) 2022 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* Flow Graph Code Example for the Userguide. +*/ + +//! Enable extended task_arena constraints feature for supporting Intel Hybrid Technology +//! and Intel Hyper-Threading Technology. +#define TBB_PREVIEW_TASK_ARENA_CONSTRAINTS_EXTENSION 1 + +#include +#include + +using namespace tbb::flow; + +//! Example shows how to set the most performant core type as the preferred one +//! for a graph execution. +static void flow_graph_attach_to_arena_1() { +/*begin_attach_to_arena_1*/ + std::vector core_types = tbb::info::core_types(); + tbb::task_arena arena( + tbb::task_arena::constraints{}.set_core_type(core_types.back()) + ); + + arena.execute( [&]() { + graph g; + function_node< int > f( g, unlimited, []( int ) { + /*the most performant core type is defined as preferred.*/ + } ); + f.try_put(1); + g.wait_for_all(); + } ); +/*end_attach_to_arena_1*/ +} + +//! Reattach existing graph to an arena with the most performant core type as +//! the preferred one for a work execution. +static void flow_graph_attach_to_arena_2() { +/*begin_attach_to_arena_2*/ + graph g; + function_node< int > f( g, unlimited, []( int ) { + /*the most performant core type is defined as preferred.*/ + } ); + + std::vector core_types = tbb::info::core_types(); + tbb::task_arena arena( + tbb::task_arena::constraints{}.set_core_type(core_types.back()) + ); + + arena.execute( [&]() { + g.reset(); + } ); + f.try_put(1); + g.wait_for_all(); +/*end_attach_to_arena_2*/ +} + +int main() { + flow_graph_attach_to_arena_1(); + flow_graph_attach_to_arena_2(); + + return 0; +} diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 0000000000..557ecc5b62 --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,53 @@ +@ECHO OFF + +rem ============================================================================ +rem Copyright (C) 2022 Intel Corporation +rem +rem Licensed under the Apache License, Version 2.0 (the "License"); +rem you may not use this file except in compliance with the License. +rem You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. +rem ============================================================================ + + + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=doc +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/test/tbb/test_partitioner.h b/test/tbb/test_partitioner.h index 073ca17c47..81cb738ec6 100644 --- a/test/tbb/test_partitioner.h +++ b/test/tbb/test_partitioner.h @@ -481,50 +481,6 @@ class SplitConstructorAssertedRange { } }; -/* - * Possible use cases are: - * ------------------------------------------------------------------------------------------------------------- - * Range# is_splittable_in_proportion Range proportional ctor Used partitioner Result Effect - * ------------------------------------------------------------------------------------------------------------- - * 1 true available proportional pMN, r(p), part(p) - * ------------------------------------------------------------------------------------------------------------- - * 2 false available proportional p11, r(p), part(p) - * ------------------------------------------------------------------------------------------------------------- - * 3 not defined available proportional p11, r(p), part(p) - * ------------------------------------------------------------------------------------------------------------- - * 4 true not available proportional pMN, r(s), part(p) * - * ------------------------------------------------------------------------------------------------------------- - * 5 false not available proportional p11, r(s), part(p) - * ------------------------------------------------------------------------------------------------------------- - * 6 not defined not available proportional p11, r(s), part(p) - * ------------------------------------------------------------------------------------------------------------- - * 1 true available simple s, r(s), part(s) - * ------------------------------------------------------------------------------------------------------------- - * 2 false available simple s, r(s), part(s) - * ------------------------------------------------------------------------------------------------------------- - * 3 not defined available simple s, r(s), part(s) - * ------------------------------------------------------------------------------------------------------------- - * 4 true not available simple s, r(s), part(s) - * ------------------------------------------------------------------------------------------------------------- - * 5 false not available simple s, r(s), part(s) - * ------------------------------------------------------------------------------------------------------------- - * 6 not defined not available simple s, r(s), part(s) - * ------------------------------------------------------------------------------------------------------------- - * - * Legend: - * proportional - with proportional splits (e.g. affinity_partitioner) - * simple - without proportional splits (e.g. simple_partitioner, auto_partitioner) - * pMN - proportional_split object with proportion M to N is created. (p11 - proportion 1 to 1) - * s - split object is created - * r(p) - range's proportional split constructor is called - * r(s) - range's ordinary split constructor is called - * part(p) - partitioner's proportional split constructor is called - * part(s) - partitioner's ordinary split constructor is called - * * - incorrect split behavior is possible (e.g. partitioner divides at an arbitrary ratio while - * range divides into halves) - */ - - // proportional_split ctor defined class Range1: public SplitConstructorAssertedRange { public: