Compare commits

..
1 Commits
Author SHA1 Message Date
Alexandra Epanchinzeva d2da407b4d New doc 2021-08-31 11:13:53 +05:00
115 changed files with 577 additions and 1216 deletions
+1 -1
View File
@@ -16,4 +16,4 @@
# use Bazel internally. The Bazel build can have security risks or
# optimization gaps.
build --symlink_prefix=/ # Out of source build
build --symlink_prefix=/ # Out of source build
+1 -1
View File
@@ -1 +1 @@
4.2.1
4.1.0
-40
View File
@@ -1,40 +0,0 @@
### Description
_Add 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)_
### 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_
- [ ] bug fix - _change which fixes an issue_
- [ ] new feature - _change which 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_
- [ ] not needed
### Documentation
- [ ] updated in # - _add PR number_
- [ ] needs to be updated
- [ ] not needed
### Breaks backward compatibility
- [ ] Yes
- [ ] No
- [ ] Unknown
### Notify the following users
_List users with `@` to send notifications_
### Other information
+1 -2
View File
@@ -48,9 +48,8 @@ jobs:
- uses: actions/checkout@v2
- name: Run scan
run: |
command -v clang-format-10
cp -r examples examples_formatted
find examples_formatted -regex '.*\.\(cpp\|hpp\)' -exec clang-format-10 -style=file -i {} \;
find examples_formatted -regex '.*\.\(cpp\|hpp\)' -exec clang-format-9 -style=file -i {} \;
diff -r examples examples_formatted
documentation:
+3 -6
View File
@@ -35,12 +35,9 @@ cc_library(
"include/oneapi/tbb/*.h",
"include/oneapi/tbb/detail/*.h",
]),
copts = ["-w"] + select({
"@bazel_tools//platforms:windows": [
"",
],
"//conditions:default": ["-mwaitpkg"],
}),
copts = [
"-w",
],
defines =
select({
"@platforms//cpu:x86_64": ["__TBB_NO_IMPLICIT_LINKAGE"],
+19 -55
View File
@@ -1,38 +1,24 @@
# Bazel* build support
# Bazel build support
The main build system of oneTBB is CMake*.
[Bazel*](https://bazel.build/) support is community-based.
The Bazel configuration may not include recommended compiler and/or linker flags used in the official CMake configuration.
The main build system of oneTBB is CMake.
Bazel support is community-based.
The maintainers do not use Bazel internally.
The Bazel configuration may not include recommended compiler and linker flags used in official CMake configuration.
---
**NOTE**
The Bazel build of oneTBB currently only aims for a subset of oneTBB that suffices restricted use cases of the usage of oneTBB.
Pull requests to improve the Bazel build experience are welcomed.
Bazel is not recommended for use by oneTBB maintainers. Thus, it is not used internally.
The standard approach of how Bazel handles third-party libraries is static linking.
Even this is not recommended by the oneTBB maintainers this is chosen since this is considered as the best practice in the Bazel ecosystem.
---
## Example usage
1. [Install Bazel](https://docs.bazel.build/versions/main/install.html).
The Bazel oneTBB build is currently only intended for a subset of oneTBB that suffices restricted use cases.
Pull requests to improve the Bazel build experience are welcome.
The standard Bazel approach to handling third-party libraries is static linking. It is the best practice within the Bazel ecosystem.
## Using oneTBB as a dependency
This example demonstrates how to use oneTBB as a dependency within a Bazel project.
The following file structure is assumed:
```
example
├── .bazelrc
├── BUILD.bazel
├── main.cpp
└── WORKSPACE.bazel
```
2. Create the following files in one folder (this folder will be considered as the workspace folder):
_WORKSPACE.bazel_:
```python
```
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
@@ -42,11 +28,8 @@ git_repository(
)
```
In the *WORKSPACE* file, the oneTBB GitHub* repository is fetched.
_BUILD.bazel_:
```python
_BUILD_:
```
cc_binary(
name = "Demo",
srcs = ["main.cpp"],
@@ -54,11 +37,8 @@ cc_binary(
)
```
The *BUILD* file defines a binary named `Demo` that has a dependency to oneTBB.
_main.cpp_:
```c++
```
#include "oneapi/tbb/version.h"
#include <iostream>
@@ -74,23 +54,7 @@ int main() {
}
```
The expected output of this program is the current version of oneTBB.
3. Switch to the folder where you create the files.
Switch to the folder with the files created earlier and run the binary with `bazel run //:Demo`.
## Build oneTBB using Bazel
Run ```bazel build //...``` in the oneTBB root directory.
## Compiler support
The Bazel build uses the compiler flag `-mwaitpkg` in non-Windows* builds.
This flag is supported by the GNU* Compiler Collection (GCC) version 9.3, Clang* 12, and newer versions of those tools.
---
**NOTE**
To use the Bazel build with earlier versions of GCC, remove `-mwaitpkg` flag as it leads to errors during compilation.
---
4. Execute the command `bazel run //:Demo`.
As an expected output, you should see the oneTBB version.
+1 -20
View File
@@ -103,7 +103,6 @@ option(TBBMALLOC_BUILD "Enable tbbmalloc build" ON)
option(TBB_CPF "Enable preview features of the library" OFF)
option(TBB_FIND_PACKAGE "Enable search for external oneTBB using find_package instead of build from sources" OFF)
option(TBB_DISABLE_HWLOC_AUTOMATIC_SEARCH "Disable HWLOC automatic search by pkg-config tool" OFF)
option(TBB_ENABLE_IPO "Enable Interprocedural Optimization (IPO) during the compilation" ON)
if (NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
@@ -182,22 +181,6 @@ foreach(FILE_WITH_EXTRA_TARGETS ${FILES_WITH_EXTRA_TARGETS})
include(${FILE_WITH_EXTRA_TARGETS})
endforeach()
# - Enabling LTO on Android causes the NDK bug.
# NDK throws the warning: "argument unused during compilation: '-Wa,--noexecstack'"
# - For some reason GCC does not instrument code with Thread Sanitizer when lto is enabled and C linker is used.
if (TBB_ENABLE_IPO AND BUILD_SHARED_LIBS AND NOT ANDROID_PLATFORM AND NOT TBB_SANITIZE MATCHES "thread")
if (NOT CMAKE_VERSION VERSION_LESS 3.9)
cmake_policy(SET CMP0069 NEW)
include(CheckIPOSupported)
check_ipo_supported(RESULT TBB_IPO_PROPERTY)
else()
set(TBB_IPO_FLAGS TRUE)
endif()
if (TBB_IPO_PROPERTY OR TBB_IPO_FLAGS)
message(STATUS "IPO enabled")
endif()
endif()
set(TBB_COMPILER_SETTINGS_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compilers/${CMAKE_CXX_COMPILER_ID}.cmake)
if (EXISTS ${TBB_COMPILER_SETTINGS_FILE})
include(${TBB_COMPILER_SETTINGS_FILE})
@@ -217,9 +200,7 @@ else()
if (NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "mips")
if (TBBMALLOC_BUILD)
add_subdirectory(src/tbbmalloc)
if (NOT "${MSVC_CXX_ARCHITECTURE_ID}" MATCHES "ARM64")
add_subdirectory(src/tbbmalloc_proxy)
endif()
add_subdirectory(src/tbbmalloc_proxy)
endif()
if (APPLE)
message(STATUS "TBBBind build targets are disabled due to unsupported environment")
+34
View File
@@ -0,0 +1,34 @@
# Installation from Sources
Required Software:
* DPC++/C++ Compiler
* Microsoft* Visual Studio* (Windows* OS only)
* GNU Compilers (gcc) 4.8.5–10
* GNU C Library (glibc) version 2.17–2.32
* Clang* 4.2–11.0
The project uses CMake build configuration. Make sure that you have CMake version 3.1 or higher.
Before installing the library, learn how to [configure, build, and test](cmake\README.md) the project.
NOTE: Be careful about installation. Avoid commands like `make install` unless you fully understand the consequences.
The following installation components are supported:
`runtime` - oneTBB runtime package (core shared libraries and .dll files on Windows).
`devel` - oneTBB development package (header files, CMake integration files, library symbolic links, and .lib files on Windows).
`tbb4py` - oneTBB Module for Python.
To install the specific components after configuration and build, run:
```bash
cmake -DCOMPONENT=<component> [-DBUILD_TYPE=<build-type>] -P cmake_install.cmake
```
Simple packaging using CPack is supported.
The following commands allow to create a simple portable package that includes header files, libraries, and integration files for CMake:
```bash
cmake <options> ..
cpack
```
+10 -10
View File
@@ -2,21 +2,22 @@
[![Apache License Version 2.0](https://img.shields.io/badge/license-Apache_2.0-green.svg)](LICENSE.txt) [![oneTBB CI](https://github.com/oneapi-src/oneTBB/actions/workflows/ci.yml/badge.svg)](https://github.com/oneapi-src/oneTBB/actions/workflows/ci.yml?query=branch%3Amaster)
oneAPI Threading Building Blocks (oneTBB) lets you easily write parallel C++ programs that take
full advantage of multicore performance, that are portable, composable and have future-proof scalability.
full advantage of multicore performance that are portable, composable, and have future-proof scalability.
## Release Information
Here are [Release Notes](RELEASE_NOTES.md) and [System Requirements](SYSTEM_REQUIREMENTS.md).
## Installation
You can install oneTBB from [GitHub*](https://github.com/oneapi-src/oneTBB/releases).
See [Installation from Sources](INSTALL.md) for details.
## Documentation
* [oneTBB Specification](https://spec.oneapi.com/versions/latest/elements/oneTBB/source/nested-index.html)
* [oneTBB Developer Guide and Reference](https://oneapi-src.github.io/oneTBB)
* [oneTBB Developer Guide and Reference](https://oneapi-src.github.io/oneTBB/)
* [Migrating from TBB to oneTBB](https://oneapi-src.github.io/oneTBB/tbb_userguide/Migration_Guide.html)
* [README for a build system](cmake/README.md)
* [README for build system](cmake/README.md)
* [Basic support for the Bazel build system](Bazel.md)
* [oneTBB Discussions](https://github.com/oneapi-src/oneTBB/discussions)
## Support
Please report issues and suggestions via [GitHub issues](https://github.com/oneapi-src/oneTBB/issues). See our [documentation](./CONTRIBUTING.md##Issues) to learn how to work with them.
Please report issues and suggestions via
[GitHub issues](https://github.com/oneapi-src/oneTBB/issues).
## How to Contribute
We welcome community contributions, so check our [contributing guidelines](CONTRIBUTING.md)
@@ -26,9 +27,8 @@ to learn more.
oneAPI Threading Building Blocks is licensed under [Apache License, Version 2.0](LICENSE.txt).
By its terms, contributions submitted to the project are also done under that license.
## Engineering team contacts
* [Email us.](mailto:inteltbbdevelopers@intel.com)
* [E-mail us.](mailto:inteltbbdevelopers@intel.com)
------------------------------------------------------------------------
\* All names and brands may be claimed as the property of others.
\* All names and brands may be claimed as the property of others.
-52
View File
@@ -1,52 +0,0 @@
<!--
******************************************************************************
* 
* 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.
*******************************************************************************/-->
# Release Notes <!-- omit in toc -->
This document contains changes of oneTBB compared to the last release.
## Table of Contents <!-- omit in toc -->
- [Preview Features](#preview-features)
- [Known Limitations](#known-limitations)
- [Fixed Issues](#fixed-issues)
- [Open-source Contributions Integrated](#open-source-contributions-integrated)
## Preview Features
- Introduced the collaborative_call_once algorithm that executes the callable object exactly once, but allows other threads to join oneTBB parallel construction used inside this callable object. Inspired by Ben FrantzDale and Henry Heffan.
## 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.
- On Linux* OS, if oneAPI Threading Building Blocks (oneTBB) or Threading Building Blocks (TBB) are installed in a system folder like /usr/lib64, the application may fail to link due to the order in which the linker searches for libraries. Use the -L linker option to specify the correct location of oneTBB library. This issue does not affect the program execution.
- The oneapi::tbb::info namespace interfaces might unexpectedly change the process affinity mask on Windows* OS systems (see https://github.com/open-mpi/hwloc/issues/366 for details) when using hwloc version lower than 2.5.
- Using a hwloc version other than 1.11, 2.0, or 2.5 may cause an undefined behavior on Windows OS. See https://github.com/open-mpi/hwloc/issues/477 for details.
- The NUMA topology may be detected incorrectly on Windows OS machines where the number of NUMA node threads exceeds the size of 1 processor group.
- On Windows OS on ARM64*, when compiling an application using oneTBB with the Microsoft* Compiler, the compiler issues a warning C4324 that a structure was padded due to the alignment specifier. Consider suppressing the warning by specifying /wd4324 to the compiler command line.
- oneTBB does not support fork(), to work-around the issue, consider using task_scheduler_handle to join oneTBB worker threads before using fork().
## Fixed Issues
- Enabled full support of Address Sanitizer and Thread Sanitizer.
- Fixed a race condition in tbbmalloc that may cause a crash in realloc() when using tbbmalloc_proxy.
- Enabled GCC* 11 support.
- Fixed limiter_node behavior when an integral type is used as an argument for the DecrementType template parameter.
- Fixed a possible memory leak when the static or affinity partitioners are used.
- Fixed possible system oversubscription when using a process mask and an explicit number of threads in the task arena.
## Open-source Contributions Integrated
- Enabled PowerPC* Linux* OS support. Contributed by Mircho Rodozov (https://github.com/oneapi-src/oneTBB/pull/461)
- Improved UNIX* system support and enabled QNX Neutrino* RTOS support. Contributed by Pablo Romero (https://github.com/oneapi-src/oneTBB/pull/440)
- Enabled experimental Bazel* build system support. Contributed by Julian Amann (https://github.com/oneapi-src/oneTBB/pull/442)
- Enabled oneTBB build for Windows* OS on ARM64*. Contributed by Michael Vitrano (https://github.com/oneapi-src/oneTBB/pull/507)
- Added MinGW* and export attributes support. Contributed by Long Nguyen (https://github.com/oneapi-src/oneTBB/pull/351)
-63
View File
@@ -1,63 +0,0 @@
<!--
******************************************************************************
* 
* 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.
*******************************************************************************/-->
# System Requirements <!-- omit in toc -->
This document provides details about hardware, operating system, and software prerequisites for the oneAPI Threading Building Blocks (oneTBB).
## Table of Contents <!-- omit in toc -->
- [Supported Hardware](#supported-hardware)
- [Software](#software)
-[Supported Operating Systems](#supported-operating-systems)
-[Supported Compilers](#supported-compilers)
## Supported Hardware
- Intel(R) Celeron(R) processor family
- Intel(R) Core* processor family
- Intel(R) Xeon(R) processor family
- Intel(R) Xeon Phi* processor family
- Intel(R) Atom* processor family
- Non-Intel(R) processors compatible with the processors listed above
## Software
### Supported Operating Systems
- Systems with Microsoft* Windows* operating systems
- Microsoft* Windows* 10
- Microsoft* Windows* Server 2016
- Microsoft* Windows* Server 2019
- Systems with Linux* operating systems
- Clear Linux*
- Amazon* Linux 2
- CentOS* 8
- Debian* 10
- Fedora* 34
- Red Hat* Enterprise Linux* 7, 8
- SuSE* Linux* Enterprise Server 15
- Ubuntu* 18.04 LTS, 20.04, 21.04
- Systems with macOS* operating systems: macOS* 10.15, 11.x
- Systems with Android* operating systems: Android* 9
### Supported Compilers
- Intel* oneAPI DPC++/C++ Compiler
- Intel* C++ Compiler 19.0 and 19.1 version
- Microsoft* Visual C++ 14.1 (Microsoft* Visual Studio* 2017, Windows* OS only)
- Microsoft* Visual C++ 14.2 (Microsoft* Visual Studio* 2019, Windows* OS only)
- For each supported Linux* operating system, the standard gcc version provided with that operating system is supported
- GNU Compilers (gcc) 4.8.5 - 11.1.1
- GNU C Library (glibc) version 2.17 - 2.33
- Clang* 6.0.0 - 12.0.0
+1 -1
View File
@@ -16,4 +16,4 @@
# use Bazel internally. The Bazel build can have security risks or
# optimization gaps.
workspace(name = "oneTBB")
workspace(name = "oneTBB")
-1
View File
@@ -16,7 +16,6 @@ TBB_CPF:BOOL - Enable preview features of the library (OFF by default)
TBB_INSTALL_VARS:BOOL - Enable auto-generated vars installation(packages generated by `cpack` and `make install` will also include the vars script)(OFF by default)
TBB_VALGRIND_MEMCHECK:BOOL - Enable scan for memory leaks using Valgrind (OFF by default)
TBB_DISABLE_HWLOC_AUTOMATIC_SEARCH - Disable HWLOC automatic search by pkg-config tool (OFF by default)
TBB_ENABLE_IPO - Enable Interprocedural Optimization (IPO) during the compilation (ON by default)
```
## Configure, build and test
+3 -3
View File
@@ -31,9 +31,9 @@ if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
tbb_remove_compile_flag(-Werror)
endif()
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) and WAITPKG instructions support (-mwaitpkg) on relevant processors
if (NOT "${CMAKE_OSX_ARCHITECTURES}" MATCHES "^arm64$" AND CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|amd64|AMD64)") # OSX systems are 64-bit only
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm $<$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},12.0>>:-mwaitpkg>)
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) on relevant processors
if (NOT "${CMAKE_OSX_ARCHITECTURES}" MATCHES "^arm64$" AND CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|AMD64)") # OSX systems are 64-bit only
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm)
endif()
# TBB malloc settings
+7 -3
View File
@@ -44,7 +44,7 @@ if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
endif()
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) and WAITPKG instructions support (-mwaitpkg) on relevant processors
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(AMD64|amd64|i.86|x86)")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64)")
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm $<$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},12.0>>:-mwaitpkg>)
endif()
@@ -58,8 +58,12 @@ if (MINGW)
list(APPEND TBB_COMMON_COMPILE_FLAGS -U__STRICT_ANSI__)
endif()
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
# Enabling LTO on Android causes the NDK bug.
# NDK throws the warning: "argument unused during compilation: '-Wa,--noexecstack'"
if (NOT ANDROID_PLATFORM AND BUILD_SHARED_LIBS)
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
endif()
# TBB malloc settings
set(TBBMALLOC_LIB_COMPILE_FLAGS -fno-rtti -fno-exceptions)
+9 -7
View File
@@ -36,7 +36,7 @@ if (NOT CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_CXX_DEPENDS_USE_COMPILER)
endif()
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) and WAITPKG instructions support (-mwaitpkg) on relevant processors
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(AMD64|amd64|i.86|x86)")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64)")
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm $<$<AND:$<NOT:$<CXX_COMPILER_ID:Intel>>,$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},11.0>>>:-mwaitpkg>)
endif()
@@ -59,13 +59,15 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "mips")
set(TBB_TEST_COMPILE_FLAGS ${TBB_TEST_COMPILE_FLAGS} -DTBB_TEST_LOW_WORKLOAD $<$<CONFIG:DEBUG>:-mxgot>)
endif()
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
if (MINGW)
list(APPEND TBB_COMMON_COMPILE_FLAGS -U__STRICT_ANSI__)
endif()
if (MINGW AND CMAKE_SYSTEM_PROCESSOR MATCHES "i.86")
list (APPEND TBB_COMMON_COMPILE_FLAGS -msse2)
endif ()
# For some reason GCC does not instrument code with Thread Sanitizer when lto is enabled and C linker is used.
if (NOT TBB_SANITIZE MATCHES "thread")
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
endif()
# TBB malloc settings
set(TBBMALLOC_LIB_COMPILE_FLAGS -fno-rtti -fno-exceptions)
+3 -4
View File
@@ -24,7 +24,7 @@ set(TBB_WARNING_LEVEL $<$<NOT:$<CXX_COMPILER_ID:Intel>>:/W4> $<$<BOOL:${TBB_STRI
# Warning suppression C4324: structure was padded due to alignment specifier
set(TBB_WARNING_SUPPRESS /wd4324)
set(TBB_TEST_COMPILE_FLAGS ${TBB_TEST_COMPILE_FLAGS} /bigobj)
set(TBB_TEST_COMPILE_FLAGS /bigobj)
if (MSVC_VERSION LESS_EQUAL 1900)
# Warning suppression C4503 for VS2015 and earlier:
# decorated name length exceeded, name was truncated.
@@ -33,7 +33,7 @@ if (MSVC_VERSION LESS_EQUAL 1900)
set(TBB_TEST_COMPILE_FLAGS ${TBB_TEST_COMPILE_FLAGS} /wd4503)
endif()
set(TBB_LIB_COMPILE_FLAGS -D_CRT_SECURE_NO_WARNINGS /GS)
set(TBB_COMMON_COMPILE_FLAGS /volatile:iso /FS /EHsc)
set(TBB_COMMON_COMPILE_FLAGS /volatile:iso /FS)
# Ignore /WX set through add_compile_options() or added to CMAKE_CXX_FLAGS if TBB_STRICT is disabled.
if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
@@ -72,12 +72,11 @@ if (TBB_WINDOWS_DRIVER)
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "(Clang|IntelLLVM)")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64|i.86)")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64)")
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm -mwaitpkg)
endif()
set(TBB_OPENMP_NO_LINK_FLAG TRUE)
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
else()
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:/GL>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-LTCG> $<$<NOT:$<CONFIG:Debug>>:-INCREMENTAL:NO>)
-13
View File
@@ -44,16 +44,3 @@ macro(tbb_install_target target)
COMPONENT devel)
endif()
endmacro()
macro(tbb_handle_ipo target)
if (TBB_IPO_PROPERTY)
set_target_properties(${target} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
elseif (TBB_IPO_FLAGS)
target_compile_options(${target} PRIVATE ${TBB_IPO_COMPILE_FLAGS})
if (COMMAND target_link_options)
target_link_options(${target} PRIVATE ${TBB_IPO_LINK_FLAGS})
else()
target_link_libraries(${target} PRIVATE ${TBB_IPO_LINK_FLAGS})
endif()
endif()
endmacro()
-37
View File
@@ -1,37 +0,0 @@
window.MathJax = {
TeX: {
Macros: {
src: '\\operatorname{src}',
srclayer: '\\operatorname{src\\_layer}',
srciter: '\\operatorname{src\\_iter}',
srciterc: '\\operatorname{src\\_iter\\_c}',
weights: '\\operatorname{weights}',
weightslayer: '\\operatorname{weights\\_layer}',
weightsiter: '\\operatorname{weights\\_iter}',
weightspeephole: '\\operatorname{weights\\_peephole}',
weightsprojection: '\\operatorname{weights\\_projection}',
bias: '\\operatorname{bias}',
dst: '\\operatorname{dst}',
dstlayer: '\\operatorname{dst\\_layer}',
dstiter: '\\operatorname{dst\\_iter}',
dstiterc: '\\operatorname{dst\\_iter\\_c}',
diffsrc: '\\operatorname{diff\\_src}',
diffsrclayer: '\\operatorname{diff\\_src\\_layer}',
diffsrciter: '\\operatorname{diff\\_src\\_iter}',
diffsrciterc: '\\operatorname{diff\\_src\\_iter\\_c}',
diffweights: '\\operatorname{diff\\_weights}',
diffweightslayer: '\\operatorname{diff\\_weights\\_layer}',
diffweightsiter: '\\operatorname{diff\\_weights\\_iter}',
diffweightspeephole: '\\operatorname{diff\\_weights\\_peephole}',
diffweightsprojection: '\\operatorname{diff\\_weights\\_projection}',
diffbias: '\\operatorname{diff\\_bias}',
diffdst: '\\operatorname{diff\\_dst}',
diffdstlayer: '\\operatorname{diff\\_dst\\_layer}',
diffdstiter: '\\operatorname{diff\\_dst\\_iter}',
diffdstiterc: '\\operatorname{diff\\_dst\\_iter\\_c}',
diffgamma: '\\operatorname{diff\\_\\gamma}',
diffbeta: '\\operatorname{diff\\_\\beta}',
workspace: '\\operatorname{workspace}'
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

-13
View File
@@ -1,13 +0,0 @@
/* override table width restrictions */
@media screen and (min-width: 767px) {
.wy-table-responsive table td {
/* !important prevents the common CSS stylesheets from overriding
this as on RTD they are loaded after this stylesheet */
white-space: normal !important;
}
.wy-table-responsive {
overflow: visible !important;
}
}
+3 -39
View File
@@ -26,10 +26,7 @@ BUILD_TYPE = os.getenv("BUILD_TYPE")
# -- Project information -----------------------------------------------------
if BUILD_TYPE == 'oneapi' or BUILD_TYPE == 'dita':
project = u'Intel® oneAPI Threading Building Blocks (oneTBB)'
else:
project = u'oneAPI Threading Building Blocks (oneTBB)'
project = u'Intel® oneAPI Threading Building Blocks (oneTBB)'
copyright = u'2021, Intel Corporation'
author = u'Intel'
@@ -93,8 +90,7 @@ pygments_style = None
highlight_language = 'cpp'
if BUILD_TYPE == 'oneapi' or BUILD_TYPE == 'dita':
rst_prolog = """
rst_prolog = """
.. |full_name| replace:: Intel\ |reg|\ oneAPI Threading Building Blocks (oneTBB)
.. |short_name| replace:: oneTBB
.. |product| replace:: oneTBB
@@ -103,16 +99,6 @@ if BUILD_TYPE == 'oneapi' or BUILD_TYPE == 'dita':
.. |base_tk| replace:: Intel\ |reg|\ oneAPI Base Toolkit
.. |dpcpp| replace:: Intel\ |reg|\ oneAPI DPC++/C++ Compiler
"""
else:
rst_prolog = """
.. |full_name| replace:: oneAPI Threading Building Blocks (oneTBB)
.. |short_name| replace:: oneTBB
.. |product| replace:: oneTBB
.. |reg| unicode:: U+000AE
.. |copy| unicode:: U+000A9
.. |base_tk| replace:: Intel\ |reg|\ oneAPI Base Toolkit
.. |dpcpp| replace:: Intel\ |reg|\ oneAPI DPC++/C++ Compiler
"""
# -- Options for HTML output -------------------------------------------------
@@ -124,35 +110,13 @@ else:
# 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'
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': '<p align="right"><a href="https://www.intel.com/content/www/us/en/privacy/intel-cookie-notice.html">Cookies</a></p>'
}
html_theme = 'sphinx_book_theme'
# 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".
html_static_path = ['_static']
if BUILD_TYPE == 'oneapi' or BUILD_TYPE == 'dita':
html_context = {
'css_files': [
'_static/theme_overrides.css', # override wide tables in RTD theme
],
}
else:
html_js_files = ['custom.js']
html_logo = '_static/oneAPI-rgb-rev-100.png'
html_favicon = '_static/favicons.png'
# Custom sidebar templates, must be a dictionary that maps document names
+3 -27
View File
@@ -16,18 +16,9 @@ of multi-core processors. Use |short_name| to write scalable applications that:
- Emphasize data parallel programming
- Take advantage of concurrent collections and parallel algorithms
System Requirements
*******************
Refer to the `oneTBB System Requirements <https://software.intel.com/content/www/us/en/develop/articles/intel-oneapi-threading-building-blocks-system-requirements.html>`_.
Before You Begin
****************
Download |short_name| as a `stand-alone product <https://software.intel.com/content/www/us/en/develop/articles/oneapi-standalone-components.html#onetbb>`_
or as a part of the `Intel(R) oneAPI Base Toolkit <https://software.intel.com/content/www/us/en/develop/tools/oneapi/base-toolkit/download.html>`_.
After installing |short_name|, you need to set the environment variables:
#. Go to the oneTBB installation directory (``<install_dir>``). By default, ``<install_dir>`` is the following:
@@ -52,25 +43,10 @@ After installing |short_name|, you need to set the environment variables:
``vars.bat in <install_dir>/tbb/latest/env``
Example
*******
System Requirements
*******************
Below you can find a typical example for a |short_name| algorithm.
The sample calculates a sum of all integer numbers from 1 to 100.
.. code:: cpp
int sum = oneapi::tbb::parallel_reduce(oneapi::tbb::blocked_range<int>(1,101), 0,
[](oneapi::tbb::blocked_range<int> const& r, int init) -> int {
for (int v = r.begin(); v != r.end(); v++ ) {
init += v;
}
return init;
},
[](int lhs, int rhs) -> int {
return lhs + rhs;
}
);
Refer to the `oneTBB System Requirements <https://software.intel.com/content/www/us/en/develop/articles/intel-oneapi-threading-building-blocks-system-requirements.html>`_.
Find more
*********
+16
View File
@@ -1,3 +1,19 @@
//configure tms
var wapLocalCode = 'us-en';
//dynamically set per localized site, see mapping table for values
var wapSection = "oneapi-docs";
//load tms
(function() {
var host = (window.document.location.protocol == 'http:') ? "http://www.intel.com" : "https://www.intel.com";
var url = host+"/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);
})();
window.MathJax = {
TeX: {
Macros: {
-15
View File
@@ -1,15 +0,0 @@
{% extends "!layout.html" %}
{% block extrahead %}
<script defer type="text/javascript" src="https://www.intel.com/content/dam/www/global/wap/performance-config.js" ></script>
<script type="text/javascript">
// Configure TMS settings
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);
})();
</script>
{% endblock %}
+4 -4
View File
@@ -25,7 +25,7 @@ BUILD_TYPE = os.getenv("BUILD_TYPE")
# -- Project information -----------------------------------------------------
if BUILD_TYPE == 'oneapi' or BUILD_TYPE == 'dita':
if BUILD_TYPE == 'oneapi':
project = u'Intel® oneAPI Threading Building Blocks (oneTBB)'
else:
project = u'oneAPI Threading Building Blocks (oneTBB)'
@@ -90,7 +90,7 @@ pygments_style = None
# Syntax highlighting for the :: directive
highlight_language = 'cpp'
if BUILD_TYPE == 'oneapi' or BUILD_TYPE == 'dita':
if BUILD_TYPE == 'oneapi':
rst_prolog = """
.. |full_name| replace:: Intel\ |reg|\ oneAPI Threading Building Blocks (oneTBB)
.. |short_name| replace:: oneTBB
@@ -120,7 +120,7 @@ else:
# further. For a list of options available for each theme, see the
# documentation.
#
if BUILD_TYPE == 'oneapi' or BUILD_TYPE == 'dita':
if BUILD_TYPE == 'oneapi':
html_theme = 'sphinx_rtd_theme'
else:
html_theme = 'sphinx_book_theme'
@@ -140,7 +140,7 @@ else:
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
if BUILD_TYPE == 'oneapi' or BUILD_TYPE == 'dita':
if BUILD_TYPE == 'oneapi':
html_context = {
'css_files': [
'_static/theme_overrides.css', # override wide tables in RTD theme
+1 -35
View File
@@ -1,40 +1,6 @@
|full_name|
===========
This document contains information about |full_name|.
|short_name| is a flexible performance library that can be found in the |base_tk|
or as a stand-alone product. More information and specifications can be found on the
|full_name| main page.
Documentation for older versions of |short_name| is available for download only.
For a list of available documentation downloads by product version, see these pages:
* `Download Documentation for Intel Parallel Studio XE <https://software.intel.com/content/www/us/en/develop/articles/download-documentation-intel-parallel-studio-xe-current-previous.html>`_
* `Download Documentation for Intel System Studio <https://software.intel.com/content/www/us/en/develop/articles/download-documentation-intel-system-studio-current-previous.html>`_
The following are some important topics for the ``novice user``:
**Get Started with oneAPI Threading Building Blocks (oneTBB)**
`Get Started with oneTBB <https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-onetbb/top.html>`_ gives you a brief explanation of what oneTBB is.
**oneTBB Benefits**
:ref:`Benefits` describes how |short_name| differs from typical threading packages.
**Package Contents**
|short_name| includes dynamic library files and header files for Windows*, Linux*, and macOS*
operating systems as described in :ref:`Package_Contents`.
The following is important topic for the ``experienced user``:
**Migrating from Threading Building Blocks (TBB)**
Learn how to migrate from TBB to oneTBB with :ref:`Migration_Guide`.
.. toctree::
:maxdepth: 2
@@ -44,4 +10,4 @@ Learn how to migrate from TBB to oneTBB with :ref:`Migration_Guide`.
intro/Benefits
tbb_userguide/title
reference/reference
intro/notices_and_disclaimers
intro/notices_and_disclaimers
@@ -1,72 +0,0 @@
.. _parallel_sort_ranges_extension:
parallel_sort ranges interface extension
========================================
.. contents::
:local:
:depth: 1
Description
***********
|full_name| implementation extends the `oneapi::tbb::parallel_sort specification <https://spec.oneapi.io/versions/latest/elements/oneTBB/source/algorithms/functions/parallel_sort_func.html>`_
with overloads that takes the container by forwarding reference.
API
***
Header
------
.. code:: cpp
#include <oneapi/tbb/parallel_sort.h>
Syntax
------
.. code:: cpp
namespace oneapi {
namespace tbb {
template <typename Container>
void parallel_sort( Container&& c );
template <typename Container, typename Compare>
void parallel_sort( Container&& c, const Compare& comp );
} // namespace tbb
} // namespace oneapi
Functions
---------
.. cpp:function:: template <typename Container> void parallel_sort( Container&& c );
Equivalent to ``parallel_sort( std::begin(c), std::end(c), comp )``, where `comp` uses `operator<` to determine relative orderings.
.. cpp:function:: template <typename Container, typename Compare> void parallel_sort( Container&& c, const Compare& comp );
Equivalent to ``parallel_sort( std::begin(c), std::end(c), comp )``.
Example
-------
This interface may be used for sorting rvalue or constant views:
.. code:: cpp
#include <array>
#include <span> // requires C++20
#include <oneapi/tbb/parallel_sort.h>
std::span<int> get_span() {
static std::array<int, 3> arr = {3, 2, 1};
return std::span<int>(arr);
}
int main() {
tbb::parallel_sort(get_span());
}
-1
View File
@@ -18,7 +18,6 @@ It also describes features that are not included in the oneTBB specification.
info_namespace
parallel_for_each_semantics
parallel_sort_ranges_extension
Preview features
****************
+2 -1
View File
@@ -191,7 +191,8 @@ This final implementation has all of the nodes and edges from the
much advantage in using an ``input_node`` over an explicit loop. But,
because an ``input_node`` is able to react to the behavior of downstream
nodes, it can limit memory use in more complex graphs. For more
information, see:ref:`create_token_based_system` .
information, see `Creating a Token-Based
System <create_token_based_system.html#create_token_based_system>`__
.. |image0| image:: Images/flow_graph.jpg
@@ -325,131 +325,3 @@ task:
}
tg.wait();
}
Scheduler Bypass
----------------
TBB ``task::execute()`` method can return a pointer to a task that can be executed next by the current thread.
This might reduce scheduling overheads compared to direct ``spawn``. Similar to ``spawn``, the returned task
is not guaranteed to be executed next by the current thread.
.. code:: cpp
#include <tbb/task.h>
// Assuming OtherTask is defined.
struct Task : tbb::task {
task* execute(){
// some work to do ...
auto* other_p = new(this->parent().allocate_child()) OtherTask{};
this->parent().add_ref_count();
return other_p;
}
};
int main(){
// Assuming RootTask is defined.
RootTask& root = *new(tbb::task::allocate_root()) RootTask{};
Task& child = *new(root.allocate_child()) Task{/*params*/};
root.add_ref_count();
tbb::task_spawn(child);
root.wait_for_all();;
}
In oneTBB this can be done using the preview feature of ``oneapi::tbb::task_group``.
.. code:: cpp
#define TBB_PREVIEW_TASK_GROUP_EXTENSIONS 1
#include <oneapi/tbb/task_group.h>
// Assuming OtherTask is defined.
int main(){
oneapi::tbb::task_group tg;
tg.run([&tg](){
//some work to do ...
return tg.defer(OtherTask{});
});
tg.wait();
}
Here ``oneapi::tbb::task_group::defer`` adds a new task into the ``tg``. However, the task is not put into a
queue of tasks ready for execution via ``oneapi::tbb::task_group::run``, but bypassed to the executing thread directly
via function return value.
Deferred task creation
----------------------
The TBB low-level task API separates the task creation from the actual spawning. This separation allows to
postpone the task spawning, while the parent task and final result production are blocked from premature leave.
For example, ``RootTask``, ``ChildTask``, and ``CallBackTask`` are the user-side functors that
inherit ``tbb::task`` and implement its interface. Then, blocking the ``RootTask`` from leaving prematurely
and waiting on it is implemented as follows:
.. code:: cpp
#include <tbb/task.h>
int main() {
// Assuming RootTask, ChildTask, and CallBackTask are defined.
RootTask& root = *new(tbb::task::allocate_root()) RootTask{};
ChildTask& child = *new(root.allocate_child()) ChildTask{/*params*/};
CallBackTask& cb_task = *new(root.allocate_child()) CallBackTask{/*params*/};
root.set_ref_count(3);
tbb::task::spawn(child);
register_callback([cb_task&](){
tbb::task::enqueue(cb_task);
});
root.wait_for_all();
// Control flow will reach here only after both ChildTask and CallBackTask are executed,
// i.e. after the callback is called
}
In oneTBB this can be done using the preview feature of ``oneapi::tbb::task_group``.
.. code:: cpp
#define TBB_PREVIEW_TASK_GROUP_EXTENSIONS 1
#include <oneapi/tbb/task_group.h>
int main(){
oneapi::tbb::task_group tg;
oneapi::tbb::task_arena arena;
// Assuming ChildTask and CallBackTask are defined.
auto cb = tg.defer(CallBackTask{/*params*/});
register_callback([&tg, c = std::move(cb), &arena]{
arena.enqueue(c);
});
tg.run(ChildTask{/*params*/});
tg.wait();
// Control flow gets here once both ChildTask and CallBackTask are executed
// i.e. after the callback is called
}
Here ``oneapi::tbb::task_group::defer`` adds a new task into the ``tg``. However, the task is not spawned until
``oneapi::tbb::task_arena::enqueue`` is called.
.. note::
The call to ``oneapi::tbb::task_group::wait`` will not return control until both ``ChildTask`` and
``CallBackTask`` are executed.
@@ -9,7 +9,8 @@ You may not always want to block the main application thread by calling
wait_for_all(). However, it is safest to call wait_for_all on a graph
before destroying it. A common solution is to enqueue a task to build
and wait for the graph to complete. For example, assume you really do
not want to call a wait_for_all in the example from :ref:`always_use_wait_for_all`,
not want to call a wait_for_all in the example from `Always Use
wait_for_all() <always_use_wait_for_all.html#always_use_wait4all>`__,
Instead you can enqueue a task that creates the graph and waits for it:
+2 -1
View File
@@ -7,7 +7,8 @@ Use graph::reset() to Reset a Canceled Graph
When a graph execution is canceled either because of an unhandled
exception or because its task_group_context is canceled explicitly, the
graph and its nodes may be left in an indeterminate state. For example,
in the code samples shown in :ref:`cancel_a_graph` the input 2 may be
in the code samples shown in `Cancel a Graph
Explicitly <cancel_a_graph.html#cancel_a_graph>`__ the input 2 may be
left in a buffer. But even beyond remnants in the buffers, there are
other optimizations performed during the execution of a flow graph that
can leave its nodes and edges in an indeterminate state. If you want to
+2 -1
View File
@@ -29,7 +29,8 @@ All ``input_node`` objects are constructed in the inactive state and usually
activated after the entire flow graph is constructed.
For example, you can use the code in :ref:`Data_Flow_Graph`. In that implementation,
For example, you can use the code in `Data Flow
Graph <Data_Flow_Graph.html#Data_Flow_Graph>`__. In that implementation,
the ``input_node`` is constructed in the inactive state and activated after
all other edges are made:
-1
View File
@@ -121,7 +121,6 @@ if (NOT _find_index EQUAL -1)
elseif ("${EXAMPLES_UI_MODE}" STREQUAL "x")
set_x_ui_project_settings()
endif()
target_compile_options(UI_LIB_${PROJECT_NAME} PRIVATE ${TBB_CXX_STD_FLAG})
endif()
unset(_available_ui_modes)
+4 -3
View File
@@ -89,9 +89,10 @@ void video::terminate() {
#endif
g_video = 0;
running = false;
delete[] g_pImg;
g_pImg = nullptr;
if (g_pImg) {
delete[] g_pImg;
g_pImg = 0;
}
}
video::~video() {
+4 -3
View File
@@ -164,9 +164,10 @@ void video::terminate() {
m_pD2DFactory->Release();
g_video = 0;
running = false;
delete[] g_pImg;
g_pImg = 0;
if (g_pImg) {
delete[] g_pImg;
g_pImg = 0;
}
}
//////////// drawing area constructor & destructor /////////////
+8 -6
View File
@@ -123,15 +123,17 @@ bool video::init_window(int sizex, int sizey) {
}
void video::terminate() {
delete g_pBitmap;
g_pBitmap = 0;
if (g_pBitmap) {
delete g_pBitmap;
g_pBitmap = 0;
}
Gdiplus::GdiplusShutdown(gdiplusToken);
g_video = 0;
running = false;
delete[] g_pImg;
g_pImg = 0;
if (g_pImg) {
delete[] g_pImg;
g_pImg = 0;
}
}
//////////// drawing area constructor & destructor /////////////
+4 -3
View File
@@ -87,9 +87,10 @@ void video::terminate() {
}
g_video = 0;
running = false;
delete[] g_pImg;
g_pImg = 0;
if (g_pImg) {
delete[] g_pImg;
g_pImg = 0;
}
}
video::~video() {
@@ -125,8 +125,8 @@ void ParallelEvolution::Run(double execution_time, int nthread) {
break;
}
}
delete pGlobControl;
pGlobControl = nullptr;
if (pGlobControl)
delete pGlobControl;
}
/**
@@ -124,8 +124,8 @@ public:
~ParallelEvolution() {
//! delete global_control object
delete m_pGlobControl;
m_pGlobControl = nullptr;
if (m_pGlobControl != nullptr)
delete m_pGlobControl;
}
virtual void Run(double execution_time, int nthread);
virtual void Step();
+42 -32
View File
@@ -39,6 +39,7 @@ unsigned short init_values[BOARD_SIZE] = { 1, 0, 0, 9, 0, 0, 0, 8, 0, 0, 8, 0, 2
0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 7, 4, 0, 0, 7, 0, 0,
0, 3, 0, 0, 3, 0, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0,
0, 1, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0 };
oneapi::tbb::task_group *g;
double solve_time;
typedef struct {
@@ -46,8 +47,8 @@ typedef struct {
unsigned potential_set;
} board_element;
void read_board(const char* filename) {
FILE* fp;
void read_board(const char *filename) {
FILE *fp;
int input;
fp = fopen(filename, "r");
if (!fp) {
@@ -65,7 +66,7 @@ void read_board(const char* filename) {
fclose(fp);
}
void print_board(const std::vector<board_element>& b) {
void print_board(board_element *b) {
for (unsigned row = 0; row < BOARD_DIM; ++row) {
for (unsigned col = 0; col < BOARD_DIM; ++col) {
printf(" %d", b[row * BOARD_DIM + col].solved_element);
@@ -78,7 +79,7 @@ void print_board(const std::vector<board_element>& b) {
}
}
void print_potential_board(const std::vector<board_element>& b) {
void print_potential_board(board_element *b) {
for (unsigned row = 0; row < BOARD_DIM; ++row) {
for (unsigned col = 0; col < BOARD_DIM; ++col) {
if (b[row * BOARD_DIM + col].solved_element)
@@ -94,45 +95,50 @@ void print_potential_board(const std::vector<board_element>& b) {
}
}
void init_board(std::vector<board_element>& b) {
void init_board(board_element *b) {
for (unsigned i = 0; i < BOARD_SIZE; ++i)
b[i].solved_element = b[i].potential_set = 0;
}
void init_board(std::vector<board_element>& b, unsigned short arr[BOARD_SIZE]) {
void init_board(board_element *b, unsigned short arr[81]) {
for (unsigned i = 0; i < BOARD_SIZE; ++i) {
b[i].solved_element = arr[i];
b[i].potential_set = 0;
}
}
void init_potentials(std::vector<board_element>& b) {
void init_potentials(board_element *b) {
for (unsigned i = 0; i < BOARD_SIZE; ++i)
b[i].potential_set = 0;
}
bool fixed_board(const std::vector<board_element>& b) {
void copy_board(board_element *src, board_element *dst) {
for (unsigned i = 0; i < BOARD_SIZE; ++i)
dst[i].solved_element = src[i].solved_element;
}
bool fixed_board(board_element *b) {
for (int i = BOARD_SIZE - 1; i >= 0; --i)
if (b[i].solved_element == 0)
return false;
return true;
}
bool in_row(const std::vector<board_element>& b, unsigned row, unsigned col, unsigned short p) {
bool in_row(board_element *b, unsigned row, unsigned col, unsigned short p) {
for (unsigned c = 0; c < BOARD_DIM; ++c)
if (c != col && b[row * BOARD_DIM + c].solved_element == p)
return true;
return false;
}
bool in_col(const std::vector<board_element>& b, unsigned row, unsigned col, unsigned short p) {
bool in_col(board_element *b, unsigned row, unsigned col, unsigned short p) {
for (unsigned r = 0; r < BOARD_DIM; ++r)
if (r != row && b[r * BOARD_DIM + col].solved_element == p)
return true;
return false;
}
bool in_block(const std::vector<board_element>& b, unsigned row, unsigned col, unsigned short p) {
bool in_block(board_element *b, unsigned row, unsigned col, unsigned short p) {
unsigned b_row = row / 3 * 3, b_col = col / 3 * 3;
for (unsigned i = b_row; i < b_row + 3; ++i)
for (unsigned j = b_col; j < b_col + 3; ++j)
@@ -141,7 +147,7 @@ bool in_block(const std::vector<board_element>& b, unsigned row, unsigned col, u
return false;
}
void calculate_potentials(std::vector<board_element>& b) {
void calculate_potentials(board_element *b) {
for (unsigned i = 0; i < BOARD_SIZE; ++i) {
b[i].potential_set = 0;
if (!b[i].solved_element) { // element is not yet fixed
@@ -155,7 +161,7 @@ void calculate_potentials(std::vector<board_element>& b) {
}
}
bool valid_board(const std::vector<board_element>& b) {
bool valid_board(board_element *b) {
bool success = true;
for (unsigned i = 0; i < BOARD_SIZE; ++i) {
if (success && b[i].solved_element) { // element is fixed
@@ -169,7 +175,7 @@ bool valid_board(const std::vector<board_element>& b) {
return success;
}
bool examine_potentials(std::vector<board_element>& b, bool& progress) {
bool examine_potentials(board_element *b, bool *progress) {
bool singletons = false;
for (unsigned i = 0; i < BOARD_SIZE; ++i) {
if (b[i].solved_element == 0 && b[i].potential_set == 0) // empty set
@@ -222,58 +228,62 @@ bool examine_potentials(std::vector<board_element>& b, bool& progress) {
}
}
}
progress = singletons;
*progress = singletons;
return valid_board(b);
}
void partial_solve(oneapi::tbb::task_group& g,
std::vector<board_element>& b,
unsigned first_potential_set) {
void partial_solve(board_element *b, unsigned first_potential_set) {
if (fixed_board(b)) {
if (find_one)
g.cancel();
g->cancel();
if (++nSols == 1 && verbose) {
print_board(b);
}
free(b);
return;
}
calculate_potentials(b);
bool progress = true;
bool success = examine_potentials(b, progress);
bool success = examine_potentials(b, &progress);
if (success && progress) {
partial_solve(g, b, first_potential_set);
partial_solve(b, first_potential_set);
}
else if (success && !progress) {
board_element *new_board;
while (b[first_potential_set].solved_element != 0)
++first_potential_set;
for (unsigned short potential = 1; potential <= BOARD_DIM; ++potential) {
if (1 << (potential - 1) & b[first_potential_set].potential_set) {
g.run([&g, b /*make a copy of the board*/, first_potential_set, potential]() {
//as task_group treat passed in functor as const - const_cast is needed
//to allow modification of the copy
auto& new_board = const_cast<std::vector<board_element>&>(b);
new_board[first_potential_set].solved_element = potential;
partial_solve(g, new_board, first_potential_set);
new_board = (board_element *)malloc(BOARD_SIZE * sizeof(board_element));
copy_board(b, new_board);
new_board[first_potential_set].solved_element = potential;
g->run([=] {
partial_solve(new_board, first_potential_set);
});
}
}
free(b);
}
else {
free(b);
}
}
unsigned solve(int p) {
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, p);
nSols = 0;
std::vector<board_element> start_board(BOARD_SIZE);
board_element *start_board = (board_element *)malloc(BOARD_SIZE * sizeof(board_element));
init_board(start_board, init_values);
oneapi::tbb::task_group g;
g = new oneapi::tbb::task_group;
oneapi::tbb::tick_count t0 = oneapi::tbb::tick_count::now();
partial_solve(g, start_board, 0);
g.wait();
partial_solve(start_board, 0);
g->wait();
solve_time = (oneapi::tbb::tick_count::now() - t0).seconds();
delete g;
return nSols;
}
int main(int argc, char* argv[]) {
int main(int argc, char *argv[]) {
oneapi::tbb::tick_count mainStartTime = oneapi::tbb::tick_count::now();
utility::thread_number_range threads(utility::get_default_num_threads);
+3 -3
View File
@@ -19,9 +19,9 @@
#if __TBB_PREVIEW_COLLABORATIVE_CALL_ONCE
#include "task_arena.h"
#include "task_group.h"
#include "task.h"
#include "tbb/task_arena.h"
#include "tbb/task_group.h"
#include "tbb/task.h"
#include <atomic>
+1 -2
View File
@@ -329,8 +329,7 @@
#define __TBB_TSX_INTRINSICS_PRESENT (__RTM__ || __INTEL_COMPILER || (_MSC_VER>=1700 && (__TBB_x86_64 || __TBB_x86_32)))
#define __TBB_WAITPKG_INTRINSICS_PRESENT ((__INTEL_COMPILER >= 1900 || __TBB_GCC_VERSION >= 110000 || __TBB_CLANG_VERSION >= 120000) \
&& (_WIN32 || _WIN64 || __unix__ || __APPLE__) && (__TBB_x86_32 || __TBB_x86_64) && !__ANDROID__)
#define __TBB_WAITPKG_INTRINSICS_PRESENT ((__INTEL_COMPILER >= 1900 || __TBB_GCC_VERSION >= 110000 || __TBB_CLANG_VERSION >= 120000) && !__ANDROID__)
/** Internal TBB features & modes **/
@@ -82,8 +82,7 @@ public:
// TODO: pass the graph_buffer_policy to the base so it can allocate the queue instead.
// This would be an interface-breaking change.
virtual ~function_input_base() {
delete my_queue;
my_queue = nullptr;
if ( my_queue ) delete my_queue;
}
graph_task* try_put_task( const input_type& t) override {
@@ -180,8 +180,7 @@ public:
~hash_buffer() {
internal_free_buffer(pointer_array, elements_array, my_size, nelements);
delete my_key;
my_key = nullptr;
if(my_key) delete my_key;
}
hash_buffer(const hash_buffer&) = delete;
hash_buffer& operator=(const hash_buffer&) = delete;
-2
View File
@@ -29,9 +29,7 @@
#include <intrin.h>
#ifdef __TBBMALLOC_BUILD
#define WIN32_LEAN_AND_MEAN
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h> // SwitchToThread()
#endif
#ifdef _MSC_VER
+4 -4
View File
@@ -79,10 +79,10 @@ class rw_scoped_lock {
public:
//! Construct lock that has not acquired a mutex.
/** Equivalent to zero-initialization of *this. */
constexpr rw_scoped_lock() noexcept {}
constexpr rw_scoped_lock() noexcept : m_mutex(nullptr), m_is_writer(false) {}
//! Acquire lock on given mutex.
rw_scoped_lock(Mutex& m, bool write = true) {
rw_scoped_lock(Mutex& m, bool write = true) : m_mutex(nullptr) {
acquire(m, write);
}
@@ -160,11 +160,11 @@ public:
protected:
//! The pointer to the current mutex that is held, or nullptr if no mutex is held.
Mutex* m_mutex {nullptr};
Mutex* m_mutex{};
//! If mutex != nullptr, then is_writer is true if holding a writer lock, false if holding a reader lock.
/** Not defined if not holding a lock. */
bool m_is_writer {false};
bool m_is_writer{};
};
} // namespace d1
+1 -1
View File
@@ -54,7 +54,7 @@ public:
suppress_unused_warning(m_version_and_traits);
}
~task_handle_task() override {
~task_handle_task(){
m_wait_ctx.release();
}
+1 -1
View File
@@ -129,7 +129,7 @@ public:
task_scheduler_handle& operator=(const task_scheduler_handle& other) = delete;
//! Move only
task_scheduler_handle(task_scheduler_handle&& other) noexcept {
task_scheduler_handle(task_scheduler_handle&& other) noexcept : m_ctl{nullptr} {
std::swap(m_ctl, other.m_ctl);
}
task_scheduler_handle& operator=(task_scheduler_handle&& other) noexcept {
+4 -1
View File
@@ -22,7 +22,6 @@
#if __TBB_ARENA_BINDING
#include <vector>
#include <cstdint>
namespace tbb {
namespace detail {
@@ -38,6 +37,10 @@ struct constraints {
constraints(numa_node_id id = -1, int maximal_concurrency = -1)
: numa_id(id)
, max_concurrency(maximal_concurrency)
#if __TBB_PREVIEW_TASK_ARENA_CONSTRAINTS_EXTENSION_PRESENT
, core_type(-1)
, max_threads_per_core(-1)
#endif
{}
#endif /*!__TBB_CPP20_PRESENT*/
+4 -4
View File
@@ -236,7 +236,7 @@ void parallel_sort( RandomAccessIterator begin, RandomAccessIterator end, const
}
}
//! Sorts the data in [begin,end) with a default comparator \c std::less
//! Sorts the data in [begin,end) with a default comparator \c std::less<RandomAccessIterator>
/** @ingroup algorithms **/
template<typename RandomAccessIterator>
__TBB_requires(std::random_access_iterator<RandomAccessIterator> &&
@@ -250,16 +250,16 @@ void parallel_sort( RandomAccessIterator begin, RandomAccessIterator end ) {
template<typename Range, typename Compare>
__TBB_requires(container_based_sequence<Range, std::random_access_iterator_tag> &&
compare<Compare, range_iterator_type<Range>>)
void parallel_sort( Range&& rng, const Compare& comp ) {
void parallel_sort( Range& rng, const Compare& comp ) {
parallel_sort(std::begin(rng), std::end(rng), comp);
}
//! Sorts the data in rng with a default comparator \c std::less
//! Sorts the data in rng with a default comparator \c std::less<RandomAccessIterator>
/** @ingroup algorithms **/
template<typename Range>
__TBB_requires(container_based_sequence<Range, std::random_access_iterator_tag> &&
less_than_comparable<typename std::iterator_traits<range_iterator_type<Range>>::value_type>)
void parallel_sort( Range&& rng ) {
void parallel_sort( Range& rng ) {
parallel_sort(std::begin(rng), std::end(rng));
}
//@}
+6 -3
View File
@@ -486,7 +486,8 @@ struct dynamic_grainsize_mode : Mode {
class auto_partition_type: public dynamic_grainsize_mode<adaptive_mode<auto_partition_type> > {
public:
auto_partition_type( const auto_partitioner& ) {
auto_partition_type( const auto_partitioner& )
: dynamic_grainsize_mode<adaptive_mode<auto_partition_type> >() {
my_divisor *= __TBB_INITIAL_CHUNKS;
}
auto_partition_type( auto_partition_type& src, split)
@@ -532,7 +533,8 @@ public:
class static_partition_type : public linear_affinity_mode<static_partition_type> {
public:
typedef detail::proportional_split split_type;
static_partition_type( const static_partitioner& ) {}
static_partition_type( const static_partitioner& )
: linear_affinity_mode<static_partition_type>() {}
static_partition_type( static_partition_type& p, const proportional_split& split_obj )
: linear_affinity_mode<static_partition_type>(p, split_obj) {}
};
@@ -543,7 +545,8 @@ class affinity_partition_type : public dynamic_grainsize_mode<linear_affinity_mo
public:
static const unsigned factor = 1 << factor_power; // number of slots in affinity array per task
typedef detail::proportional_split split_type;
affinity_partition_type( affinity_partitioner_base& ap ) {
affinity_partition_type( affinity_partitioner_base& ap )
: dynamic_grainsize_mode<linear_affinity_mode<affinity_partition_type> >() {
__TBB_ASSERT( (factor&(factor-1))==0, "factor must be power of two" );
ap.resize(factor);
my_array = ap.my_array;
-28
View File
@@ -524,28 +524,6 @@ protected:
return cancellation_status ? canceled : complete;
}
#if __TBB_PREVIEW_TASK_GROUP_EXTENSIONS
task_group_status internal_run_and_wait(d2::task_handle&& h) {
if (h == nullptr) {
throw_exception(exception_id::bad_task_handle);
}
using acs = d2::task_handle_accessor;
if (&acs::ctx_of(h) != &context()) {
throw_exception(exception_id::bad_task_handle_wrong_task_group);
}
bool cancellation_status = false;
try_call([&] {
execute_and_wait(*acs::release(h), context(), m_wait_ctx, context());
}).on_completion([&] {
// TODO: the reset method is not thread-safe. Ensure the correct behavior.
cancellation_status = context().is_group_execution_cancelled();
context().reset();
});
return cancellation_status ? canceled : complete;
}
#endif
template<typename F>
task* prepare_task(F&& f) {
m_wait_ctx.reserve();
@@ -654,12 +632,6 @@ public:
task_group_status run_and_wait(const F& f) {
return internal_run_and_wait(f);
}
#if __TBB_PREVIEW_TASK_GROUP_EXTENSIONS
task_group_status run_and_wait(d2::task_handle&& h) {
return internal_run_and_wait(std::move(h));
}
#endif
}; // class task_group
#if TBB_PREVIEW_ISOLATED_TASK_GROUP
+2 -2
View File
@@ -23,7 +23,7 @@
// Product version
#define TBB_VERSION_MAJOR 2021
// Update version
#define TBB_VERSION_MINOR 6
#define TBB_VERSION_MINOR 4
// "Patch" version for custom releases
#define TBB_VERSION_PATCH 0
// Suffix string
@@ -34,7 +34,7 @@
// OneAPI oneTBB specification version
#define ONETBB_SPEC_VERSION "1.0"
// Full interface version
#define TBB_INTERFACE_VERSION 12060
#define TBB_INTERFACE_VERSION 12040
// Major interface version
#define TBB_INTERFACE_VERSION_MAJOR (TBB_INTERFACE_VERSION/1000)
// Minor interface version
+2 -4
View File
@@ -48,14 +48,12 @@ if /i "%1"=="all" (set TBB_TARGET_VS=vc_mt) & shift & goto ParseAr
:SetEnv
if exist "%TBBROOT%\redist\%TBB_TARGET_ARCH%\%TBB_TARGET_VS%\tbb12.dll" (
set "TBB_DLL_PATH=%TBBROOT%\redist\%TBB_TARGET_ARCH%\%TBB_TARGET_VS%"
set "PATH=%TBBROOT%\redist\%TBB_TARGET_ARCH%\%TBB_TARGET_VS%;%PATH%"
)
if exist "%TBBROOT%\..\redist\%TBB_TARGET_ARCH%\tbb\%TBB_TARGET_VS%\tbb12.dll" (
set "TBB_DLL_PATH=%TBBROOT%\..\redist\%TBB_TARGET_ARCH%\tbb\%TBB_TARGET_VS%"
set "PATH=%TBBROOT%\..\redist\%TBB_TARGET_ARCH%\tbb\%TBB_TARGET_VS%;%PATH%"
)
set "PATH=%TBB_DLL_PATH%;%PATH%"
set "LIB=%TBBROOT%\lib\%TBB_TARGET_ARCH%\%TBB_TARGET_VS%;%LIB%"
set "INCLUDE=%TBBROOT%\include;%INCLUDE%"
set "CPATH=%TBBROOT%\include;%CPATH%"
-1
View File
@@ -18,7 +18,6 @@ REM
@echo off
set "TBBROOT=@TBBROOT_REPLACEMENT@"
set "TBB_DLL_PATH=@BINARY_PATH_REPLACEMENT@"
set "INCLUDE=%TBBROOT%\include;%INCLUDE%"
set "CPATH=%TBBROOT%\include;%CPATH%"
@@ -28,25 +28,25 @@
<ItemDefinitionGroup Condition="$(Configuration.ToLower().Contains('release')) AND '$(Platform)' == 'Win32'">
<Link>
<AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)..\..\lib\native\win-x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>tbb12.lib;tbbmalloc.lib;tbbmalloc_proxy.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>tbb12.lib;tbbmalloc.lib;tbbmalloc_proxy.lib;tbbproxy.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="$(Configuration.ToLower().Contains('release')) AND '$(Platform)' == 'x64'">
<Link>
<AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)..\..\lib\native\win-x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>tbb12.lib;tbbmalloc.lib;tbbmalloc_proxy.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>tbb12.lib;tbbmalloc.lib;tbbmalloc_proxy.lib;tbbproxy.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="$(Configuration.ToLower().Contains('debug')) AND '$(Platform)' == 'Win32'">
<Link>
<AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)..\..\lib\native\win-x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>tbb12_debug.lib;tbbmalloc_debug.lib;tbbmalloc_proxy_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>tbb12_debug.lib;tbbmalloc_debug.lib;tbbmalloc_proxy_debug.lib;tbbproxy_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="$(Configuration.ToLower().Contains('debug')) AND '$(Platform)' == 'x64'">
<Link>
<AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)..\..\lib\native\win-x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>tbb12_debug.lib;tbbmalloc_debug.lib;tbbmalloc_proxy_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>tbb12_debug.lib;tbbmalloc_debug.lib;tbbmalloc_proxy_debug.lib;tbbproxy_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
-1
View File
@@ -34,7 +34,6 @@ string(STRIP "${TBB4PY_INCLUDE_STRING}" TBB4PY_INCLUDE_STRING)
add_custom_target(
python_build
ALL
DEPENDS tbb python_copy
COMMAND
${PYTHON_EXECUTABLE} ${PYTHON_BUILD_WORK_DIR}/setup.py
+3 -2
View File
@@ -79,6 +79,7 @@ target_compile_options(tbb
${TBB_WARNING_SUPPRESS}
${TBB_LIB_COMPILE_FLAGS}
${TBB_COMMON_COMPILE_FLAGS}
${TBB_IPO_COMPILE_FLAGS}
)
# Avoid use of target_link_libraries here as it changes /DEF option to \DEF on Windows.
@@ -88,8 +89,6 @@ set_target_properties(tbb PROPERTIES
SOVERSION ${TBB_BINARY_VERSION}
)
tbb_handle_ipo(tbb)
if (TBB_DEF_FILE_PREFIX) # If there's no prefix, assume we're using export directives
set_target_properties(tbb PROPERTIES
LINK_FLAGS ${TBB_LINK_DEF_FILE_FLAG}${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbb.def
@@ -104,12 +103,14 @@ if (COMMAND target_link_options)
PRIVATE
${TBB_LIB_LINK_FLAGS}
${TBB_COMMON_LINK_FLAGS}
${TBB_IPO_LINK_FLAGS}
)
else()
target_link_libraries(tbb
PRIVATE
${TBB_LIB_LINK_FLAGS}
${TBB_COMMON_LINK_FLAGS}
${TBB_IPO_LINK_FLAGS}
)
endif()
+4 -4
View File
@@ -28,12 +28,12 @@ namespace r1 {
struct address_context {
address_context() = default;
address_context(void* address, std::uintptr_t context) :
my_address(address), my_context(context)
address_context(void* address, std::uintptr_t contex) :
my_address(address), my_contex(contex)
{}
void* my_address{nullptr};
std::uintptr_t my_context{0};
std::uintptr_t my_contex{0};
};
class address_waiter : public concurrent_monitor_base<address_context> {
@@ -75,7 +75,7 @@ void notify_by_address(void* address, std::uintptr_t target_context) {
address_waiter& waiter = get_address_waiter(address);
auto predicate = [address, target_context] (address_context ctx) {
return ctx.my_address == address && ctx.my_context == target_context;
return ctx.my_address == address && ctx.my_contex == target_context;
};
waiter.notify_relaxed(predicate);
+3 -3
View File
@@ -27,11 +27,11 @@
#include <cstdlib>
#ifdef _WIN32
#include <windows.h>
#if _WIN32 || _WIN64
#include <Windows.h>
#else
#include <dlfcn.h>
#endif
#endif /* _WIN32||_WIN64 */
#if __TBB_WEAK_SYMBOLS_PRESENT
+2 -2
View File
@@ -49,7 +49,7 @@ public:
restore_affinity_mask(my_binding_handler, this_task_arena::current_thread_index());
}
~numa_binding_observer() override{
~numa_binding_observer(){
destroy_binding_handler(my_binding_handler);
}
};
@@ -631,7 +631,7 @@ class delegated_task : public d1::task {
public:
delegated_task(d1::delegate_base& d, concurrent_monitor& s, d1::wait_context& wo)
: m_delegate(d), m_monitor(s), m_wait_ctx(wo), m_completed{ false }{}
~delegated_task() override {
~delegated_task() {
// The destructor can be called earlier than the m_monitor is notified
// because the waiting thread can be released after m_wait_ctx.release_wait.
// To close that race we wait for the m_completed signal.
+12 -15
View File
@@ -217,6 +217,9 @@ struct arena_base : padded<intrusive_list_node> {
task_stream<back_nonnull_accessor> my_critical_task_stream;
#endif
//! The number of workers requested by the external thread owning the arena.
unsigned my_max_num_workers;
//! The total number of workers that are requested from the resource manager.
int my_total_num_workers_requested;
@@ -251,9 +254,18 @@ struct arena_base : padded<intrusive_list_node> {
//! The market that owns this arena.
market* my_market;
//! ABA prevention marker.
std::uintptr_t my_aba_epoch;
//! Default task group context.
d1::task_group_context* my_default_ctx;
//! The number of slots in the arena.
unsigned my_num_slots;
//! The number of reserved slots (can be occupied only by external threads).
unsigned my_num_reserved_slots;
#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
// arena needs an extra worker despite a global limit
std::atomic<bool> my_global_concurrency_mode;
@@ -272,21 +284,6 @@ struct arena_base : padded<intrusive_list_node> {
int my_local_concurrency_requests;
#endif /* __TBB_ENQUEUE_ENFORCED_CONCURRENCY*/
//! ABA prevention marker.
std::uintptr_t my_aba_epoch;
//! The number of slots in the arena.
unsigned my_num_slots;
//! The number of reserved slots (can be occupied only by external threads).
unsigned my_num_reserved_slots;
//! The number of workers requested by the external thread owning the arena.
unsigned my_max_num_workers;
//! The target serialization epoch for callers of adjust_job_count_estimate
int my_adjust_demand_target_epoch;
//! The current serialization epoch for callers of adjust_job_count_estimate
d1::waitable_atomic<int> my_adjust_demand_current_epoch;
#if TBB_USE_ASSERT
//! Used to trap accesses to the object after its destruction.
std::uintptr_t my_guard;
+2 -1
View File
@@ -148,7 +148,8 @@ class sleep_node : public wait_node<Context> {
public:
using base_type::base_type;
~sleep_node() override {
// Make it virtual due to Intel Compiler warning
virtual ~sleep_node() {
if (this->my_initialized) {
if (this->my_skipped_wakeup) semaphore().P();
semaphore().~binary_semaphore();
+1 -1
View File
@@ -281,13 +281,13 @@ namespace r1 {
}
if ( fname_len>0 ) {
ap_data._len += fname_len;
if ( ap_data._len>PATH_MAX ) {
DYNAMIC_LINK_WARNING( dl_buff_too_small );
ap_data._len=0;
return;
}
std::strncpy( ap_data._path+rc, dlinfo.dli_fname, fname_len );
ap_data._len += fname_len;
ap_data._path[ap_data._len]=0;
}
#endif /* _WIN32 */
+2 -2
View File
@@ -29,8 +29,8 @@
and CLOSE_INTERNAL_NAMESPACE to override the following default definitions. **/
#include <cstddef>
#ifdef _WIN32
#include <windows.h>
#if _WIN32
#include <Windows.h>
#endif /* _WIN32 */
namespace tbb {
+10 -10
View File
@@ -59,19 +59,19 @@ public:
};
class alignas(max_nfs_size) allowed_parallelism_control : public control_storage {
std::size_t default_value() const override {
virtual std::size_t default_value() const override {
return max(1U, governor::default_num_threads());
}
bool is_first_arg_preferred(std::size_t a, std::size_t b) const override {
virtual bool is_first_arg_preferred(std::size_t a, std::size_t b) const override {
return a<b; // prefer min allowed parallelism
}
void apply_active(std::size_t new_active) override {
virtual void apply_active(std::size_t new_active) override {
control_storage::apply_active(new_active);
__TBB_ASSERT( my_active_value>=1, NULL );
// -1 to take external thread into account
market::set_active_num_workers( my_active_value-1 );
}
std::size_t active_value() override {
virtual std::size_t active_value() override {
spin_mutex::scoped_lock lock(my_list_mutex); // protect my_list.empty() call
if (my_list.empty())
return default_value();
@@ -88,10 +88,10 @@ public:
};
class alignas(max_nfs_size) stack_size_control : public control_storage {
std::size_t default_value() const override {
virtual std::size_t default_value() const override {
return ThreadStackSize;
}
void apply_active(std::size_t new_active) override {
virtual void apply_active(std::size_t new_active) override {
control_storage::apply_active(new_active);
#if __TBB_WIN8UI_SUPPORT && (_WIN32_WINNT < 0x0A00)
__TBB_ASSERT( false, "For Windows 8 Store* apps we must not set stack size" );
@@ -100,20 +100,20 @@ class alignas(max_nfs_size) stack_size_control : public control_storage {
};
class alignas(max_nfs_size) terminate_on_exception_control : public control_storage {
std::size_t default_value() const override {
virtual std::size_t default_value() const override {
return 0;
}
};
#if __TBB_SUPPORTS_WORKERS_WAITING_IN_TERMINATE
class alignas(max_nfs_size) lifetime_control : public control_storage {
bool is_first_arg_preferred(std::size_t, std::size_t) const override {
virtual bool is_first_arg_preferred(std::size_t, std::size_t) const override {
return false; // not interested
}
std::size_t default_value() const override {
virtual std::size_t default_value() const override {
return 0;
}
void apply_active(std::size_t new_active) override {
virtual void apply_active(std::size_t new_active) override {
if (new_active == 1) {
// reserve the market reference
market::global_market_mutex_type::scoped_lock lock( market::theMarketMutex );
+2 -2
View File
@@ -82,11 +82,11 @@ struct task_proxy : public d1::task {
return nullptr;
}
task* execute(d1::execution_data&) override {
virtual task* execute(d1::execution_data&) {
__TBB_ASSERT_RELEASE(false, nullptr);
return nullptr;
}
task* cancel(d1::execution_data&) override {
virtual task* cancel(d1::execution_data&) {
__TBB_ASSERT_RELEASE(false, nullptr);
return nullptr;
}
+4 -4
View File
@@ -578,14 +578,14 @@ void market::adjust_demand ( arena& a, int delta, bool mandatory ) {
my_num_workers_requested += delta;
__TBB_ASSERT(my_num_workers_requested <= (int)effective_soft_limit, NULL);
target_epoch = a.my_adjust_demand_target_epoch++;
target_epoch = my_adjust_demand_target_epoch++;
}
a.my_adjust_demand_current_epoch.wait_until(target_epoch, /* context = */ target_epoch, std::memory_order_relaxed);
my_adjust_demand_current_epoch.wait_until(target_epoch, /* context = */ target_epoch, std::memory_order_acquire);
// Must be called outside of any locks
my_server->adjust_job_count_estimate( delta );
a.my_adjust_demand_current_epoch.exchange(target_epoch + 1);
a.my_adjust_demand_current_epoch.notify_relaxed(target_epoch + 1);
my_adjust_demand_current_epoch.exchange(target_epoch + 1);
my_adjust_demand_current_epoch.notify_relaxed(target_epoch + 1);
}
void market::process( job& j ) {
+7 -1
View File
@@ -105,6 +105,12 @@ private:
//! Number of workers currently requested from RML
int my_num_workers_requested;
//! The target serialization epoch for callers of adjust_job_count_estimate
int my_adjust_demand_target_epoch;
//! The current serialization epoch for callers of adjust_job_count_estimate
d1::waitable_atomic<int> my_adjust_demand_current_epoch;
//! First unused index of worker
/** Used to assign indices to the new workers coming from RML, and busy part
of my_workers array. **/
@@ -228,7 +234,7 @@ public:
unsigned arena_index, std::size_t stack_size );
//! Removes the arena from the market's list
void try_destroy_arena ( arena*, uintptr_t aba_epoch, unsigned priority_level );
void try_destroy_arena ( arena*, uintptr_t aba_epoch, unsigned pririty_level );
//! Removes the arena from the market's list
void detach_arena ( arena& );
+1 -1
View File
@@ -46,7 +46,7 @@ public:
, my_suspend_point(my_curr_dispatcher->get_suspend_point())
{}
~resume_node() override {
virtual ~resume_node() {
if (this->my_skipped_wakeup) {
spin_wait_until_eq(this->my_notify_calls, 1);
}
+7 -4
View File
@@ -90,8 +90,9 @@ static basic_mask_t* process_mask;
static int num_masks;
void destroy_process_mask() {
delete [] process_mask;
process_mask = nullptr;
if( process_mask ) {
delete [] process_mask;
}
}
#define curMaskSize sizeof(basic_mask_t) * num_masks
@@ -120,8 +121,10 @@ void affinity_helper::protect_affinity_mask( bool restore_process_mask ) {
}
}
void affinity_helper::dismiss() {
delete [] threadMask;
threadMask = NULL;
if( threadMask ) {
delete [] threadMask;
threadMask = NULL;
}
is_changed = 0;
}
#undef curMaskSize
+1 -1
View File
@@ -331,7 +331,7 @@ public:
return nullptr;
}
~stage_task() override {
~stage_task() {
if ( my_filter && my_object ) {
my_filter->finalize(my_object);
my_object = nullptr;
+2 -2
View File
@@ -96,7 +96,7 @@ private:
protected:
private_worker( private_server& server, tbb_client& client, const std::size_t i ) :
my_state(st_init), my_server(server), my_client(client), my_index(i),
my_handle(), my_next()
my_thread_monitor(), my_handle(), my_next()
{}
};
@@ -165,7 +165,7 @@ private:
//! Equivalent of adding additional_slack to my_slack and waking up to 2 threads if my_slack permits.
void wake_some( int additional_slack );
~private_server() override;
virtual ~private_server();
void remove_server_ref() {
if( --my_ref_count==0 ) {
+55 -109
View File
@@ -168,11 +168,7 @@ struct queuing_rw_mutex_impl {
s.my_state.store(d1::queuing_rw_mutex::scoped_lock::state_t(write ? STATE_WRITER : STATE_READER), std::memory_order_relaxed);
s.my_internal_lock.store(RELEASED, std::memory_order_relaxed);
// The CAS must have release semantics, because we are
// "sending" the fields initialized above to other actors.
// We need acquire semantics, because we are acquiring the predecessor (or mutex if no predecessor)
queuing_rw_mutex::scoped_lock* predecessor = m.q_tail.exchange(&s, std::memory_order_acq_rel);
queuing_rw_mutex::scoped_lock* predecessor = m.q_tail.exchange(&s, std::memory_order_release);
if( write ) { // Acquiring for write
@@ -181,8 +177,7 @@ struct queuing_rw_mutex_impl {
predecessor = tricky_pointer(predecessor) & ~FLAG;
__TBB_ASSERT( !predecessor->my_next, "the predecessor has another successor!");
tricky_pointer::store(predecessor->my_next, &s, std::memory_order_release);
// We are acquiring the mutex
spin_wait_until_eq(s.my_going, 1U, std::memory_order_acquire);
spin_wait_until_eq(s.my_going, 1U);
}
} else { // Acquiring for read
@@ -199,18 +194,10 @@ struct queuing_rw_mutex_impl {
} else {
// Load predecessor->my_state now, because once predecessor->my_next becomes
// non-NULL, we must assume that *predecessor might be destroyed.
pred_state = predecessor->my_state.load(std::memory_order_relaxed);
if (pred_state == STATE_READER) {
// Notify the previous reader to unblock us.
predecessor->my_state.compare_exchange_strong(pred_state, STATE_READER_UNBLOCKNEXT, std::memory_order_relaxed);
}
if (pred_state == STATE_ACTIVEREADER) { // either we initially read it or CAS failed
// Active reader means that the predecessor already acquired the mutex and cannot notify us.
// Therefore, we need to acquire the mutex ourselves by re-reading predecessor state.
(void)predecessor->my_state.load(std::memory_order_acquire);
}
pred_state = STATE_READER;
predecessor->my_state.compare_exchange_strong(pred_state, STATE_READER_UNBLOCKNEXT, std::memory_order_acq_rel);
}
tricky_pointer::store(s.my_prev, predecessor, std::memory_order_relaxed);
tricky_pointer::store(s.my_prev, predecessor, std::memory_order_relaxed); // TODO: order?
__TBB_ASSERT( !( tricky_pointer(predecessor) & FLAG ), "use of corrupted pointer!" );
__TBB_ASSERT( !predecessor->my_next.load(std::memory_order_relaxed), "the predecessor has another successor!");
tricky_pointer::store(predecessor->my_next, &s, std::memory_order_release);
@@ -219,18 +206,13 @@ struct queuing_rw_mutex_impl {
sync_prepare_done = true;
ITT_NOTIFY(sync_prepare, s.my_mutex);
#endif
// We are acquiring the mutex
spin_wait_until_eq(s.my_going, 1U, std::memory_order_acquire);
}
}
// The protected state must have been acquired here before it can be further released to any other reader(s):
unsigned char old_state = STATE_READER;
// When this reader is signaled by previous actor it acquires the mutex.
// We need to build happens-before relation with all other coming readers that will read our ACTIVEREADER
// without blocking on my_going. Therefore, we need to publish ACTIVEREADER with release semantics.
// On fail it is relaxed, because we will build happens-before on my_going.
s.my_state.compare_exchange_strong(old_state, STATE_ACTIVEREADER, std::memory_order_release, std::memory_order_relaxed);
s.my_state.compare_exchange_strong(old_state, STATE_ACTIVEREADER, std::memory_order_acq_rel);
if( old_state!=STATE_READER ) {
#if __TBB_USE_ITT_NOTIFY
if( !sync_prepare_done )
@@ -238,16 +220,20 @@ struct queuing_rw_mutex_impl {
#endif
// Failed to become active reader -> need to unblock the next waiting reader first
__TBB_ASSERT( s.my_state.load(std::memory_order_relaxed)==STATE_READER_UNBLOCKNEXT, "unexpected state" );
spin_wait_while_eq(s.my_next, 0U, std::memory_order_acquire);
spin_wait_while_eq(s.my_next, 0U);
/* my_state should be changed before unblocking the next otherwise it might finish
and another thread can get our old state and left blocked */
s.my_state.store(STATE_ACTIVEREADER, std::memory_order_relaxed);
tricky_pointer::load(s.my_next, std::memory_order_relaxed)->my_going.store(1U, std::memory_order_release);
}
__TBB_ASSERT(s.my_state.load(std::memory_order_relaxed) == STATE_ACTIVEREADER, "unlocked reader is active reader");
__TBB_ASSERT( s.my_state.load(std::memory_order_relaxed) ==STATE_ACTIVEREADER, "unlocked reader is active reader" );
}
ITT_NOTIFY(sync_acquired, s.my_mutex);
// Force acquire so that user's critical section receives correct values
// from processor that was previously in the user's critical section.
atomic_fence(std::memory_order_acquire); // TODO: consider exchange on line 171
}
//! A method to acquire queuing_rw_mutex if it is free
@@ -267,11 +253,13 @@ struct queuing_rw_mutex_impl {
s.my_internal_lock.store(RELEASED, std::memory_order_relaxed);
// The CAS must have release semantics, because we are
// "sending" the fields initialized above to other actors.
// We need acquire semantics, because we are acquiring the mutex
// "sending" the fields initialized above to other processors.
d1::queuing_rw_mutex::scoped_lock* expected = nullptr;
if (!m.q_tail.compare_exchange_strong(expected, &s, std::memory_order_acq_rel))
if (!m.q_tail.compare_exchange_strong(expected, &s, std::memory_order_release))
return false; // Someone already took the lock
// Force acquire so that user's critical section receives correct values
// from processor that was previously in the user's critical section.
atomic_fence(std::memory_order_acquire);
s.my_mutex = &m;
ITT_NOTIFY(sync_acquired, s.my_mutex);
return true;
@@ -292,50 +280,32 @@ struct queuing_rw_mutex_impl {
d1::queuing_rw_mutex::scoped_lock* next = tricky_pointer::load(s.my_next, std::memory_order_acquire);
if( !next ) {
d1::queuing_rw_mutex::scoped_lock* expected = &s;
// Release mutex on success otherwise wait for successor publication
if( s.my_mutex->q_tail.compare_exchange_strong(expected, nullptr,
std::memory_order_release, std::memory_order_relaxed) )
{
if( s.my_mutex->q_tail.compare_exchange_strong(expected, nullptr, std::memory_order_release) ) {
// this was the only item in the queue, and the queue is now empty.
goto done;
}
spin_wait_while_eq(s.my_next, 0U, std::memory_order_relaxed);
spin_wait_while_eq(s.my_next, 0U);
next = tricky_pointer::load(s.my_next, std::memory_order_acquire);
}
next->my_going.store(2U, std::memory_order_relaxed); // protect next queue node from being destroyed too early
// If the next is STATE_UPGRADE_WAITING, it is expected to acquire all other released readers via release
// sequence in next->my_state. In that case, we need to preserve release sequence in next->my_state
// contributed by other reader. So, there are two approaches not to break the release sequence:
// 1. Use read-modify-write (exchange) operation to store with release the UPGRADE_LOSER state;
// 2. Acquire the release sequence and store the sequence and UPGRADE_LOSER state.
// The second approach seems better on x86 because it does not involve interlocked operations.
// Therefore, we read next->my_state with acquire while it is not required for else branch to get the
// release sequence.
if( next->my_state.load(std::memory_order_acquire)==STATE_UPGRADE_WAITING ) {
if( next->my_state.load()==STATE_UPGRADE_WAITING ) {
// the next waiting for upgrade means this writer was upgraded before.
acquire_internal_lock(s);
// Responsibility transition, the one who reads uncorrupted my_prev will do release.
// Guarantee that above store of 2 into next->my_going happens-before resetting of next->my_prev
d1::queuing_rw_mutex::scoped_lock* tmp = tricky_pointer::exchange(next->my_prev, nullptr, std::memory_order_release);
// Pass the release sequence that we acquired with the above load of next->my_state.
next->my_state.store(STATE_UPGRADE_LOSER, std::memory_order_release);
// We are releasing the mutex
next->my_state.store(STATE_UPGRADE_LOSER, std::memory_order_relaxed);
next->my_going.store(1U, std::memory_order_release);
unblock_or_wait_on_internal_lock(s, get_flag(tmp));
} else {
// next->state cannot be STATE_UPGRADE_REQUESTED
__TBB_ASSERT( next->my_state.load(std::memory_order_relaxed) & (STATE_COMBINED_WAITINGREADER | STATE_WRITER), "unexpected state" );
__TBB_ASSERT( !( next->my_prev.load(std::memory_order_relaxed) & FLAG ), "use of corrupted pointer!" );
// Guarantee that above store of 2 into next->my_going happens-before resetting of next->my_prev
tricky_pointer::store(next->my_prev, nullptr, std::memory_order_release);
// We are releasing the mutex
tricky_pointer::store(next->my_prev, nullptr, std::memory_order_relaxed);
next->my_going.store(1U, std::memory_order_release);
}
} else { // Acquired for read
// The basic idea it to build happens-before relation with left and right readers via prev and next. In addition,
// the first reader should acquire the left (prev) signal and propagate to right (next). To simplify, we always
// build happens-before relation between left and right (left is happened before right).
queuing_rw_mutex::scoped_lock *tmp = nullptr;
retry:
// Addition to the original paper: Mark my_prev as in use
@@ -347,9 +317,12 @@ struct queuing_rw_mutex_impl {
// Failed to acquire the lock on predecessor. The predecessor either unlinks or upgrades.
// In the second case, it could or could not know my "in use" flag - need to check
// Responsibility transition, the one who reads uncorrupted my_prev will do release.
tmp = tricky_pointer::compare_exchange_strong(s.my_prev, tricky_pointer(predecessor) | FLAG, predecessor, std::memory_order_acquire);
tmp = tricky_pointer::compare_exchange_strong(s.my_prev, tricky_pointer(predecessor) | FLAG, predecessor, std::memory_order_release);
if( !(tricky_pointer(tmp) & FLAG) ) {
// Wait for the predecessor to change my_prev (e.g. during unlink)
// TODO: spin_wait condition seems never reachable
__TBB_ASSERT(tricky_pointer::load(s.my_prev, std::memory_order_relaxed) != (tricky_pointer(predecessor) | FLAG), nullptr);
tricky_pointer::spin_wait_while_eq( s.my_prev, tricky_pointer(predecessor)|FLAG );
// Now owner of predecessor is waiting for _us_ to release its lock
release_internal_lock(*predecessor);
}
@@ -365,13 +338,13 @@ struct queuing_rw_mutex_impl {
tricky_pointer::store(predecessor->my_next, nullptr, std::memory_order_release);
d1::queuing_rw_mutex::scoped_lock* expected = &s;
if( !tricky_pointer::load(s.my_next, std::memory_order_acquire) && !s.my_mutex->q_tail.compare_exchange_strong(expected, predecessor, std::memory_order_release) ) {
if( !tricky_pointer::load(s.my_next, std::memory_order_relaxed) && !s.my_mutex->q_tail.compare_exchange_strong(expected, predecessor, std::memory_order_release) ) {
spin_wait_while_eq( s.my_next, 0U, std::memory_order_acquire );
}
__TBB_ASSERT( !(s.my_next.load(std::memory_order_relaxed) & FLAG), "use of corrupted pointer" );
// my_next is acquired either with load or spin_wait.
if(d1::queuing_rw_mutex::scoped_lock *const l_next = tricky_pointer::load(s.my_next, std::memory_order_relaxed) ) { // I->next != nil, TODO: rename to next after clearing up and adapting the n in the comment two lines below
// ensure acquire semantics of reading 'my_next'
if(d1::queuing_rw_mutex::scoped_lock *const l_next = tricky_pointer::load(s.my_next, std::memory_order_acquire) ) { // I->next != nil, TODO: rename to next after clearing up and adapting the n in the comment two lines below
// Equivalent to I->next->prev = I->prev but protected against (prev[n]&FLAG)!=0
tmp = tricky_pointer::exchange(l_next->my_prev, predecessor, std::memory_order_release);
// I->prev->next = I->next;
@@ -386,12 +359,9 @@ struct queuing_rw_mutex_impl {
d1::queuing_rw_mutex::scoped_lock* next = tricky_pointer::load(s.my_next, std::memory_order_acquire);
if( !next ) {
d1::queuing_rw_mutex::scoped_lock* expected = &s;
// Release mutex on success otherwise wait for successor publication
if( !s.my_mutex->q_tail.compare_exchange_strong(expected, nullptr,
std::memory_order_release, std::memory_order_relaxed) )
{
spin_wait_while_eq( s.my_next, 0U, std::memory_order_relaxed );
next = tricky_pointer::load(s.my_next, std::memory_order_acquire);
if( !s.my_mutex->q_tail.compare_exchange_strong(expected, nullptr, std::memory_order_release) ) {
spin_wait_while_eq( s.my_next, 0U );
next = tricky_pointer::load(s.my_next, std::memory_order_relaxed);
} else {
goto unlock_self;
}
@@ -405,8 +375,7 @@ struct queuing_rw_mutex_impl {
unblock_or_wait_on_internal_lock(s, get_flag(tmp));
}
done:
// Lifetime synchronization, no need to build happens-before relation
spin_wait_while_eq( s.my_going, 2U, std::memory_order_relaxed );
spin_wait_while_eq( s.my_going, 2U );
s.initialize();
}
@@ -415,41 +384,26 @@ struct queuing_rw_mutex_impl {
if ( s.my_state.load(std::memory_order_relaxed) == STATE_ACTIVEREADER ) return true; // Already a reader
ITT_NOTIFY(sync_releasing, s.my_mutex);
d1::queuing_rw_mutex::scoped_lock* next = tricky_pointer::load(s.my_next, std::memory_order_acquire);
if( !next ) {
s.my_state.store(STATE_READER, std::memory_order_seq_cst);
s.my_state.store(STATE_READER, std::memory_order_relaxed);
if( ! tricky_pointer::load(s.my_next, std::memory_order_relaxed)) {
// the following load of q_tail must not be reordered with setting STATE_READER above
if( &s == s.my_mutex->q_tail.load(std::memory_order_seq_cst) ) {
if( &s==s.my_mutex->q_tail.load() ) {
unsigned char old_state = STATE_READER;
// When this reader is signaled by previous actor it acquires the mutex.
// We need to build happens-before relation with all other coming readers that will read our ACTIVEREADER
// without blocking on my_going. Therefore, we need to publish ACTIVEREADER with release semantics.
// On fail it is relaxed, because we will build happens-before on my_going.
s.my_state.compare_exchange_strong(old_state, STATE_ACTIVEREADER, std::memory_order_release, std::memory_order_relaxed);
s.my_state.compare_exchange_strong(old_state, STATE_ACTIVEREADER, std::memory_order_release);
if( old_state==STATE_READER )
return true; // Downgrade completed
}
/* wait for the next to register */
spin_wait_while_eq(s.my_next, 0U, std::memory_order_relaxed);
next = tricky_pointer::load(s.my_next, std::memory_order_acquire);
spin_wait_while_eq( s.my_next, 0U );
}
d1::queuing_rw_mutex::scoped_lock *const next = tricky_pointer::load(s.my_next, std::memory_order_acquire);
__TBB_ASSERT( next, "still no successor at this point!" );
if( next->my_state.load(std::memory_order_relaxed) & STATE_COMBINED_WAITINGREADER )
if( next->my_state & STATE_COMBINED_WAITINGREADER )
next->my_going.store(1U, std::memory_order_release);
// If the next is STATE_UPGRADE_WAITING, it is expected to acquire all other released readers via release
// sequence in next->my_state. In that case, we need to preserve release sequence in next->my_state
// contributed by other reader. So, there are two approaches not to break the release sequence:
// 1. Use read-modify-write (exchange) operation to store with release the UPGRADE_LOSER state;
// 2. Acquire the release sequence and store the sequence and UPGRADE_LOSER state.
// The second approach seems better on x86 because it does not involve interlocked operations.
// Therefore, we read next->my_state with acquire while it is not required for else branch to get the
// release sequence.
else if( next->my_state.load(std::memory_order_acquire)==STATE_UPGRADE_WAITING )
else if( next->my_state==STATE_UPGRADE_WAITING )
// the next waiting for upgrade means this writer was upgraded before.
// To safe release sequence on next->my_state read it with acquire
next->my_state.store(STATE_UPGRADE_LOSER, std::memory_order_release);
s.my_state.store(STATE_ACTIVEREADER, std::memory_order_release);
next->my_state.store(STATE_UPGRADE_LOSER, std::memory_order_relaxed);
s.my_state.store(STATE_ACTIVEREADER, std::memory_order_relaxed);
return true;
}
@@ -465,20 +419,16 @@ struct queuing_rw_mutex_impl {
queuing_rw_mutex::scoped_lock* me = &s;
ITT_NOTIFY(sync_releasing, s.my_mutex);
// Publish ourselves into my_state that other UPGRADE_WAITING actors can acquire our state.
s.my_state.store(STATE_UPGRADE_REQUESTED, std::memory_order_release);
s.my_state.store(STATE_UPGRADE_REQUESTED, std::memory_order_relaxed);
requested:
__TBB_ASSERT( !(s.my_next.load(std::memory_order_relaxed) & FLAG), "use of corrupted pointer!" );
acquire_internal_lock(s);
d1::queuing_rw_mutex::scoped_lock* expected = &s;
if( !s.my_mutex->q_tail.compare_exchange_strong(expected, tricky_pointer(me)|FLAG, std::memory_order_acq_rel) ) {
spin_wait_while_eq( s.my_next, 0U, std::memory_order_relaxed );
if( !s.my_mutex->q_tail.compare_exchange_strong(expected, tricky_pointer(me)|FLAG, std::memory_order_release) ) {
spin_wait_while_eq( s.my_next, 0U );
queuing_rw_mutex::scoped_lock * next;
next = tricky_pointer::fetch_add(s.my_next, FLAG, std::memory_order_acquire);
// While we were READER the next READER might reach STATE_UPGRADE_WAITING state.
// Therefore, it did not build happens before relation with us and we need to acquire the
// next->my_state to build the happens before relation ourselves
unsigned short n_state = next->my_state.load(std::memory_order_acquire);
unsigned short n_state = next->my_state;
/* the next reader can be blocked by our state. the best thing to do is to unblock it */
if( n_state & STATE_COMBINED_WAITINGREADER )
next->my_going.store(1U, std::memory_order_release);
@@ -489,7 +439,7 @@ struct queuing_rw_mutex_impl {
// save next|FLAG for simplicity of following comparisons
tmp = tricky_pointer(next)|FLAG;
for( atomic_backoff b; tricky_pointer::load(s.my_next, std::memory_order_relaxed)==tmp; b.pause() ) {
if( s.my_state.load(std::memory_order_acquire) & STATE_COMBINED_UPGRADING ) {
if( s.my_state & STATE_COMBINED_UPGRADING ) {
if( tricky_pointer::load(s.my_next, std::memory_order_acquire)==tmp )
tricky_pointer::store(s.my_next, next, std::memory_order_relaxed);
goto waiting;
@@ -508,11 +458,7 @@ struct queuing_rw_mutex_impl {
} // if( this != my_mutex->q_tail... )
{
unsigned char old_state = STATE_UPGRADE_REQUESTED;
// If we reach STATE_UPGRADE_WAITING state we do not build happens-before relation with READER on
// left. We delegate this responsibility to READER on left when it try upgrading. Therefore, we are releasing
// on success.
// Otherwise, on fail, we already acquired the next->my_state.
s.my_state.compare_exchange_strong(old_state, STATE_UPGRADE_WAITING, std::memory_order_release, std::memory_order_relaxed);
s.my_state.compare_exchange_strong(old_state, STATE_UPGRADE_WAITING, std::memory_order_acquire);
}
waiting:
__TBB_ASSERT( !( s.my_next.load(std::memory_order_relaxed) & FLAG ), "use of corrupted pointer!" );
@@ -531,14 +477,11 @@ struct queuing_rw_mutex_impl {
// While the predecessor pointer (my_prev) is in use (FLAG is set), we can safely update the node`s state.
// Corrupted pointer transitions responsibility to release the predecessor`s node on us.
unsigned char old_state = STATE_UPGRADE_REQUESTED;
// Try to build happens before with the upgrading READER on left. If fail, the predecessor state is not
// important for us because it will acquire our state.
predecessor->my_state.compare_exchange_strong(old_state, STATE_UPGRADE_WAITING, std::memory_order_release,
std::memory_order_relaxed);
predecessor->my_state.compare_exchange_strong(old_state, STATE_UPGRADE_WAITING, std::memory_order_release);
}
if( !success ) {
// Responsibility transition, the one who reads uncorrupted my_prev will do release.
tmp = tricky_pointer::compare_exchange_strong(s.my_prev, tricky_pointer(predecessor)|FLAG, predecessor, std::memory_order_acquire);
tmp = tricky_pointer::compare_exchange_strong(s.my_prev, tricky_pointer(predecessor)|FLAG, predecessor, std::memory_order_release);
if( tricky_pointer(tmp) & FLAG ) {
tricky_pointer::spin_wait_while_eq(s.my_prev, predecessor);
predecessor = tricky_pointer::load(s.my_prev, std::memory_order_relaxed);
@@ -566,6 +509,9 @@ struct queuing_rw_mutex_impl {
// now wait for the predecessor to finish working with my fields
spin_wait_while_eq( s.my_going, 2U );
// Acquire critical section indirectly from previous owner or directly from predecessor (TODO: not clear).
atomic_fence(std::memory_order_acquire); // on either "my_mutex->q_tail" or "my_going" (TODO: not clear)
bool result = ( s.my_state != STATE_UPGRADE_LOSER );
s.my_state.store(STATE_WRITER, std::memory_order_relaxed);
s.my_going.store(1U, std::memory_order_relaxed);
+5 -10
View File
@@ -82,7 +82,7 @@ public:
friend class thread_monitor;
std::atomic<std::size_t> my_epoch{0};
};
thread_monitor() {
thread_monitor() : skipped_wakeup(false), my_sema() {
ITT_SYNC_CREATE(&my_sema, SyncType_RML, SyncObj_ThreadMonitor);
}
~thread_monitor() {}
@@ -129,7 +129,7 @@ public:
private:
cookie my_cookie; // epoch counter
std::atomic<bool> in_wait{false};
bool skipped_wakeup{false};
bool skipped_wakeup;
binary_semaphore my_sema;
#if __TBB_USE_POSIX
static void check( int error_code, const char* routine );
@@ -238,14 +238,9 @@ inline void thread_monitor::prepare_wait( cookie& c ) {
}
inline void thread_monitor::commit_wait( cookie& c ) {
bool do_it = ( c.my_epoch.load(std::memory_order_relaxed) == my_cookie.my_epoch.load(std::memory_order_acquire) );
if( do_it ) {
my_sema.P();
} else {
tbb::detail::atomic_backoff backoff;
while (in_wait.load(std::memory_order_relaxed)) { backoff.pause(); }
skipped_wakeup = true;
}
bool do_it = ( c.my_epoch.load(std::memory_order_relaxed) == my_cookie.my_epoch.load(std::memory_order_relaxed) );
if( do_it ) my_sema.P();
else cancel_wait();
}
inline void thread_monitor::cancel_wait() {
+1
View File
@@ -86,6 +86,7 @@ struct rtm_mutex_impl {
s.m_mutex = &m;
s.m_mutex->lock();
s.m_transaction_state = d1::rtm_mutex::rtm_state::rtm_real;
return;
}
//! Try to acquire lock on the given mutex.
+1
View File
@@ -97,6 +97,7 @@ struct rtm_rw_mutex_impl {
__TBB_ASSERT(!m.write_flag.load(std::memory_order_relaxed), "After acquire for write, write_flag already true");
m.write_flag.store(true, std::memory_order_relaxed); // kill transactional readers
s.m_transaction_state = d1::rtm_rw_mutex::rtm_type::rtm_real_writer;
return;
}
//! Acquire read lock on given mutex.
+2 -2
View File
@@ -175,7 +175,7 @@ public:
#endif // _WIN64
};
#if (_WIN32 || _WIN64 || __unix__ || __APPLE__) && (__TBB_x86_32 || __TBB_x86_64)
#if (_WIN32 || _WIN64 || __unix__) && (__TBB_x86_32 || __TBB_x86_64)
#if _MSC_VER
#pragma intrinsic(__rdtsc)
#endif
@@ -220,7 +220,7 @@ inline void prolonged_pause_impl() {
#endif
inline void prolonged_pause() {
#if __TBB_WAITPKG_INTRINSICS_PRESENT
#if __TBB_WAITPKG_INTRINSICS_PRESENT && (_WIN32 || _WIN64 || __unix__) && (__TBB_x86_32 || __TBB_x86_64)
if (governor::wait_package_enabled()) {
std::uint64_t time_stamp = machine_time_stamp();
// _tpause function directs the processor to enter an implementation-dependent optimized state
+1
View File
@@ -102,6 +102,7 @@ public:
, my_task_dispatcher{ nullptr }
, my_arena{}
, my_arena_slot{}
, my_inbox{}
, my_random{ this }
, my_last_observer{ nullptr }
, my_small_object_pool{new (cache_aligned_allocate(sizeof(small_object_pool_impl))) small_object_pool_impl{}}
-4
View File
@@ -147,10 +147,6 @@
# define ITT_ARCH_IA32E 2
#endif /* ITT_ARCH_IA32E */
#ifndef ITT_ARCH_IA64
# define ITT_ARCH_IA64 3
#endif /* ITT_ARCH_IA64 */
#ifndef ITT_ARCH_ARM
# define ITT_ARCH_ARM 4
#endif /* ITT_ARCH_ARM */
+3 -3
View File
@@ -46,6 +46,7 @@ function(tbbbind_build TBBBIND_NAME REQUIRED_HWLOC_TARGET)
${TBB_WARNING_LEVEL}
${TBB_LIB_COMPILE_FLAGS}
${TBB_COMMON_COMPILE_FLAGS}
${TBB_IPO_COMPILE_FLAGS}
)
# Avoid use of target_link_libraries here as it changes /DEF option to \DEF on Windows.
@@ -54,9 +55,6 @@ function(tbbbind_build TBBBIND_NAME REQUIRED_HWLOC_TARGET)
VERSION ${TBBBIND_BINARY_VERSION}.${TBB_BINARY_MINOR_VERSION}
SOVERSION ${TBBBIND_BINARY_VERSION}
)
tbb_handle_ipo(${TBBBIND_NAME})
if (TBB_DEF_FILE_PREFIX) # If there's no prefix, assume we're using export directives
set_target_properties(${TBBBIND_NAME} PROPERTIES
LINK_FLAGS ${TBB_LINK_DEF_FILE_FLAG}${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbbind.def
@@ -71,12 +69,14 @@ function(tbbbind_build TBBBIND_NAME REQUIRED_HWLOC_TARGET)
PRIVATE
${TBB_LIB_LINK_FLAGS}
${TBB_COMMON_LINK_FLAGS}
${TBB_IPO_LINK_FLAGS}
)
else()
target_link_libraries(${TBBBIND_NAME}
PRIVATE
${TBB_LIB_LINK_FLAGS}
${TBB_COMMON_LINK_FLAGS}
${TBB_IPO_LINK_FLAGS}
)
endif()
+1
View File
@@ -14,6 +14,7 @@
EXPORTS
global
__TBB_internal_initialize_system_topology
__TBB_internal_apply_affinity
__TBB_internal_restore_affinity
+1
View File
@@ -14,6 +14,7 @@
EXPORTS
global
__TBB_internal_initialize_system_topology
__TBB_internal_apply_affinity
__TBB_internal_restore_affinity
+5 -5
View File
@@ -405,7 +405,7 @@ class binding_handler {
affinity_masks_container affinity_backup;
system_topology::affinity_mask handler_affinity_mask;
#ifdef _WIN32
#if WIN32
affinity_masks_container affinity_buffer;
int my_numa_node_id;
int my_core_type_id;
@@ -415,7 +415,7 @@ class binding_handler {
public:
binding_handler( std::size_t size, int numa_node_id, int core_type_id, int max_threads_per_core )
: affinity_backup(size)
#ifdef _WIN32
#if WIN32
, affinity_buffer(size)
, my_numa_node_id(numa_node_id)
, my_core_type_id(core_type_id)
@@ -424,7 +424,7 @@ public:
{
for (std::size_t i = 0; i < size; ++i) {
affinity_backup[i] = system_topology::instance().allocate_process_affinity_mask();
#ifdef _WIN32
#if WIN32
affinity_buffer[i] = system_topology::instance().allocate_process_affinity_mask();
#endif
}
@@ -436,7 +436,7 @@ public:
~binding_handler() {
for (std::size_t i = 0; i < affinity_backup.size(); ++i) {
system_topology::instance().free_affinity_mask(affinity_backup[i]);
#ifdef _WIN32
#if WIN32
system_topology::instance().free_affinity_mask(affinity_buffer[i]);
#endif
}
@@ -452,7 +452,7 @@ public:
topology.store_current_affinity_mask(affinity_backup[slot_num]);
#ifdef _WIN32
#if WIN32
// TBBBind supports only systems where NUMA nodes and core types do not cross the border
// between several processor groups. So if a certain NUMA node or core type constraint
// specified, then the constraints affinity mask will not cross the processor groups' border.
+3 -2
View File
@@ -59,6 +59,7 @@ target_compile_options(tbbmalloc
${TBB_LIB_COMPILE_FLAGS}
${TBBMALLOC_LIB_COMPILE_FLAGS}
${TBB_COMMON_COMPILE_FLAGS}
${TBB_IPO_COMPILE_FLAGS}
)
enable_language(C)
@@ -71,8 +72,6 @@ set_target_properties(tbbmalloc PROPERTIES
LINKER_LANGUAGE C
)
tbb_handle_ipo(tbbmalloc)
if (TBB_DEF_FILE_PREFIX) # If there's no prefix, assume we're using export directives
set_target_properties(tbbmalloc PROPERTIES
LINK_FLAGS ${TBB_LINK_DEF_FILE_FLAG}${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbmalloc.def
@@ -89,12 +88,14 @@ if (COMMAND target_link_options)
PRIVATE
${TBB_LIB_LINK_FLAGS}
${TBB_COMMON_LINK_FLAGS}
${TBB_IPO_LINK_FLAGS}
)
else()
target_link_libraries(tbbmalloc
PRIVATE
${TBB_LIB_LINK_FLAGS}
${TBB_COMMON_LINK_FLAGS}
${TBB_IPO_LINK_FLAGS}
)
endif()
-4
View File
@@ -61,10 +61,6 @@ static inline bool isPowerOfTwoAtLeast(uintptr_t arg, uintptr_t power2) {
return arg && tbb::detail::is_power_of_two_at_least(arg,power2);
}
inline void do_yield() {
tbb::detail::yield();
}
#define USE_DEFAULT_MEMORY_MAPPING 1
// To support malloc replacement
+2 -2
View File
@@ -162,7 +162,7 @@ bool BackRefMain::requestNewSpace()
static_assert(!(blockSpaceSize % BackRefBlock::bytes),
"Must request space for whole number of blocks.");
if (BackRefMain::dataSz <= lastUsed + 1) // no space in main
if (backRefMain.load(std::memory_order_relaxed)->dataSz <= lastUsed + 1) // no space in main
return false;
// only one thread at a time may add blocks
@@ -181,7 +181,7 @@ bool BackRefMain::requestNewSpace()
MallocMutex::scoped_lock lock(mainMutex); // ... and share under lock
const size_t numOfUnusedIdxs = BackRefMain::dataSz - lastUsed - 1;
const size_t numOfUnusedIdxs = backRefMain.load(std::memory_order_relaxed)->dataSz - lastUsed - 1;
if (numOfUnusedIdxs <= 0) { // no space in main under lock, roll back
backend->putBackRefSpace(newBl, blockSpaceSize, isRawMemUsed);
return false;
+5 -2
View File
@@ -28,6 +28,7 @@
#define TlsGetValue_func pthread_getspecific
#define GetMyTID() pthread_self()
#include <sched.h>
inline void do_yield() {sched_yield();}
extern "C" { static void mallocThreadShutdownNotification(void*); }
#if __sun || __SUNPRO_CC
#define __asm__ asm
@@ -42,10 +43,12 @@
#define TlsAlloc() FlsAlloc(NULL)
#define TLS_ALLOC_FAILURE FLS_OUT_OF_INDEXES
#define TlsFree FlsFree
inline void do_yield() {std::this_thread::yield();}
#else
#define TlsSetValue_func TlsSetValue
#define TlsGetValue_func TlsGetValue
#define TLS_ALLOC_FAILURE TLS_OUT_OF_INDEXES
inline void do_yield() {SwitchToThread();}
#endif
#else
#error Must define USE_PTHREAD or USE_WINTHREAD
@@ -260,7 +263,7 @@ class MemoryPool {
// and set reasonable low granularity
static const size_t defaultGranularity = estimatedCacheLineSize;
MemoryPool() = delete; // deny
MemoryPool(); // deny
public:
static MallocMutex memPoolListLock;
@@ -543,7 +546,7 @@ public:
static const int POOL_LOW_MARK = 8;
class ResOfGet {
ResOfGet() = delete;
ResOfGet();
public:
Block* block;
bool lastAccMiss;
+1 -1
View File
@@ -90,7 +90,7 @@ T min ( const T& val1, const T& val2 ) {
// TODO: add a constructor to remove warnings suppression
struct parseFileItem {
const char* format;
long long& value;
unsigned long long& value;
};
#if defined(_MSC_VER) && (_MSC_VER<1900) && !defined(__INTEL_COMPILER)
+9 -9
View File
@@ -447,31 +447,31 @@ private:
void parseSystemMemInfo() {
bool hpAvailable = false;
bool thpAvailable = false;
long long hugePageSize = -1;
unsigned long long hugePageSize = 0;
#if __unix__
// Check huge pages existence
long long meminfoHugePagesTotal = 0;
unsigned long long meminfoHugePagesTotal = 0;
parseFileItem meminfoItems[] = {
// Parse system huge page size
{ "Hugepagesize: %lld kB", hugePageSize },
{ "Hugepagesize: %llu kB", hugePageSize },
// Check if there are preallocated huge pages on the system
// https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
{ "HugePages_Total: %lld", meminfoHugePagesTotal } };
{ "HugePages_Total: %llu", meminfoHugePagesTotal } };
parseFile</*BUFF_SIZE=*/100>("/proc/meminfo", meminfoItems);
// Double check another system information regarding preallocated
// huge pages if there are no information in /proc/meminfo
long long vmHugePagesTotal = 0;
unsigned long long vmHugePagesTotal = 0;
parseFileItem vmItem[] = { { "%lld", vmHugePagesTotal } };
parseFileItem vmItem[] = { { "%llu", vmHugePagesTotal } };
// We parse a counter number, it can't be huge
parseFile</*BUFF_SIZE=*/100>("/proc/sys/vm/nr_hugepages", vmItem);
if (hugePageSize > -1 && (meminfoHugePagesTotal > 0 || vmHugePagesTotal > 0)) {
if (meminfoHugePagesTotal > 0 || vmHugePagesTotal > 0) {
MALLOC_ASSERT(hugePageSize != 0, "Huge Page size can't be zero if we found preallocated.");
// Any non zero value clearly states that there are preallocated
@@ -480,11 +480,11 @@ private:
}
// Check if there is transparent huge pages support on the system
long long thpPresent = 'n';
unsigned long long thpPresent = 'n';
parseFileItem thpItem[] = { { "[alwa%cs] madvise never\n", thpPresent } };
parseFile</*BUFF_SIZE=*/100>("/sys/kernel/mm/transparent_hugepage/enabled", thpItem);
if (hugePageSize > -1 && thpPresent == 'y') {
if (thpPresent == 'y') {
MALLOC_ASSERT(hugePageSize != 0, "Huge Page size can't be zero if we found thp existence.");
thpAvailable = true;
}
+1 -1
View File
@@ -602,7 +602,7 @@ if (TARGET TBB::tbbmalloc)
endif()
# Thread Sanitizer overloads memory management routines that conflicts with tbbmalloc_proxy.
if (BUILD_SHARED_LIBS AND NOT TBB_SANITIZE MATCHES "thread" AND NOT MSVC_CXX_ARCHITECTURE_ID MATCHES "ARM64")
if (BUILD_SHARED_LIBS AND NOT TBB_SANITIZE MATCHES "thread")
# Define TBB malloc proxy tests
tbb_add_lib_test(SUBDIR tbbmalloc NAME test_malloc_atexit DEPENDENCIES TBB::tbbmalloc_proxy TBB::tbbmalloc)
tbb_add_test(SUBDIR tbbmalloc NAME test_malloc_atexit DEPENDENCIES TBB::tbbmalloc_proxy TBB::tbbmalloc _test_malloc_atexit)
+1 -1
View File
@@ -391,8 +391,8 @@ public:
};
StaticSharedCountingAllocator() = default;
StaticSharedCountingAllocator( const StaticSharedCountingAllocator& ) = default;
StaticSharedCountingAllocator& operator=( const StaticSharedCountingAllocator& ) = default;
template <typename U>
StaticSharedCountingAllocator( const StaticSharedCountingAllocator<U>& other) : alloc_base_type(other) {}
+2 -3
View File
@@ -310,15 +310,14 @@ struct harness_mapped_receiver : public tbb::flow::receiver<T> {
virtual
#endif
~harness_mapped_receiver() {
delete my_multiset;
my_multiset = nullptr;
if ( my_multiset ) delete my_multiset;
}
void initialize_map( const T& m, size_t c ) {
my_count = 0;
max_value = m;
num_copies = c;
delete my_multiset;
if ( my_multiset ) delete my_multiset;
my_multiset = new multiset_type;
}
+8 -13
View File
@@ -141,32 +141,27 @@ namespace utils {
#if __unix__
inline bool isTHPEnabledOnMachine() {
long long thpPresent = 'n';
long long hugePageSize = -1;
unsigned long long thpPresent = 'n';
parseFileItem thpItem[] = { { "[alwa%cs] madvise never\n", thpPresent } };
parseFileItem hpSizeItem[] = { { "Hugepagesize: %lld kB", hugePageSize } };
parseFile</*BUFF_SIZE=*/100>("/sys/kernel/mm/transparent_hugepage/enabled", thpItem);
parseFile</*BUFF_SIZE=*/100>("/proc/meminfo", hpSizeItem);
if (hugePageSize > -1 && thpPresent == 'y') {
if (thpPresent == 'y') {
return true;
} else {
return false;
}
}
inline long long getSystemTHPAllocatedSize() {
long long anonHugePagesSize = 0;
inline unsigned long long getSystemTHPAllocatedSize() {
unsigned long long anonHugePagesSize = 0;
parseFileItem meminfoItems[] = {
{ "AnonHugePages: %lld kB", anonHugePagesSize } };
{ "AnonHugePages: %llu kB", anonHugePagesSize } };
parseFile</*BUFF_SIZE=*/100>("/proc/meminfo", meminfoItems);
return anonHugePagesSize;
}
inline long long getSystemTHPCount() {
long long anonHugePages = 0;
inline unsigned long long getSystemTHPCount() {
unsigned long long anonHugePages = 0;
parseFileItem vmstatItems[] = {
{ "nr_anon_transparent_hugepages %lld", anonHugePages } };
{ "nr_anon_transparent_hugepages %llu", anonHugePages } };
parseFile</*BUFF_SIZE=*/100>("/proc/vmstat", vmstatItems);
return anonHugePages;
}
+3 -2
View File
@@ -37,12 +37,13 @@
#endif
#include <string.h>
#include <sched.h>
#if __FreeBSD__
#elif __FreeBSD__
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/param.h>
#include <sys/cpuset.h>
#endif
#endif
#include <thread>
namespace utils {
+2 -2
View File
@@ -22,8 +22,8 @@
#if __TBB_DYNAMIC_LOAD_ENABLED
#ifdef _WIN32
#include <windows.h>
#if _WIN32 || _WIN64
#include <Windows.h>
#else
#include <dlfcn.h>
#endif
-4
View File
@@ -53,10 +53,6 @@
// Suppress "typedef ignored ... when no variable is declared" warning by vc14
#pragma warning (push)
#pragma warning (disable: 4091)
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#include <dbghelp.h>
#pragma warning (pop)
#pragma comment (lib, "dbghelp.lib")

Some files were not shown because too many files have changed in this diff Show More