From 6c8cccae3aa7342dccd0e0dc8d11a92f5f27908c Mon Sep 17 00:00:00 2001 From: mhucka Date: Wed, 18 Jun 2025 17:52:51 +0000 Subject: [PATCH 1/6] Correct the default Bazel vector instructions options The documented way that `bazel build`, `bazel test`, and similar commands behave without options like `--config=avx` is that the AVX, SSE, and other optimization options are not applied. However, this was not what was happening: the default ended up applying them. The previous changes to `.bazelrc` and `dev_tools/test_libs.sh` that I did in PR #758 and other recent PRs not fully address this. The changes here invert the way `--build_tag_filters` and `--test_tag_filters` are used: they are set to filter out things tagged with `avx` and `sse` by default in `.bazelrc`, and options like `--config=sse` add the things back. To make this work, `dev_tools/test_libs.sh` has to be updated as well. --- .bazelrc | 41 +++++++++++++++++++++++++++-------------- dev_tools/test_libs.sh | 10 +++++----- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/.bazelrc b/.bazelrc index 13df9a666..14f35e638 100644 --- a/.bazelrc +++ b/.bazelrc @@ -23,26 +23,35 @@ common --verbose_failures # Windows uses slightly different syntax. common --enable_platform_specific_config -build:linux --copt=-std=c++17 -build:linux --cxxopt=-std=c++17 +build:linux --copt -std=c++17 +build:linux --cxxopt -std=c++17 -build:macos --copt=-std=c++17 -build:macos --cxxopt=-std=c++17 +build:macos --copt -std=c++17 +build:macos --cxxopt -std=c++17 -build:windows --copt=/std:c++17 -build:windows --cxxopt=/std:c++17 +build:windows --copt /std:c++17 +build:windows --cxxopt /std:c++17 -build --copt=-D_GLIBCXX_USE_CXX11_ABI=1 -build --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=1 +build --copt -D_GLIBCXX_USE_CXX11_ABI=1 +build --cxxopt -D_GLIBCXX_USE_CXX11_ABI=1 -# Test flags -test --test_output=errors -test --test_timeout=600 +# The default for vector instruction sets is to exclude them. +# Config options later in this file can be layered to enable them. +build --build_tag_filters=-avx,-sse +test --test_tag_filters=-avx,-sse +# "bazel run" inherits options from "build". Our run targets don't have tags, +# so we must clear the filter explicitly or we get "No targets found to run". +run:sse --build_tag_filters= +run:avx --build_tag_filters= # CUDA options build:cuda --@local_config_cuda//:enable_cuda build:cuda --define=using_cuda=true --define=using_cuda_nvcc=true +# Test flags +test --test_output=errors +test --test_timeout=600 + # Configs for verbose builds & tests common:verbose --announce_rc common:verbose --auto_output_filter=none @@ -60,12 +69,12 @@ build:sanitizer --copt -fno-omit-frame-pointer # Address sanitizer build:asan --config=sanitizer build:asan --copt -fsanitize=address -build:asan --linkopt -fsanitize=address +build:asan --linkopt=-fsanitize=address # Memory sanitizer build:msan --config=sanitizer build:msan --copt -fsanitize=leak -build:msan --linkopt -fsanitize=leak +build:msan --linkopt=-fsanitize=leak # No sanitizers build:nosan -- @@ -77,10 +86,14 @@ build:nosan -- build:avx --copt -O3 build:avx --copt -mavx2 build:avx --copt -mfma +build:avx --build_tag_filters=avx --ui_event_filters=-WARNING +test:avx --test_tag_filters=avx --ui_event_filters=-WARNING # Build with SSE build:sse --copt -O3 build:sse --copt -msse4 +build:sse --build_tag_filters=sse --ui_event_filters=-WARNING +test:sse --test_tag_filters=sse --ui_event_filters=-WARNING # Build without AVX or SSE build:basic --copt -O3 @@ -90,7 +103,7 @@ build:basic --copt -O3 # Build with OpenMP build:openmp --copt -fopenmp -build:openmp --linkopt -lgomp +build:openmp --linkopt=-lgomp # No OpenMP build:nopenmp -- diff --git a/dev_tools/test_libs.sh b/dev_tools/test_libs.sh index 02702a336..58fc54289 100755 --- a/dev_tools/test_libs.sh +++ b/dev_tools/test_libs.sh @@ -28,12 +28,12 @@ if [[ "$1" == "-h" || "$1" == "--help" || "$1" == "help" ]]; then exit 0 fi -# Unless we can tell this system supports AVX, we skip those tests. +# Look for AVX and SSE in the processor's feature flags. declare features="" declare filters="" features="$(python -c 'import cpuinfo; print(" ".join(cpuinfo.get_cpu_info().get("flags", [])))')" -[[ "$features" == *avx2* ]] || filters+=",-avx" -[[ "$features" == *sse* ]] || filters+=",-sse" +[[ "$features" == *avx2* ]] && filters+=",avx" +[[ "$features" == *sse* ]] && filters+=",sse" filters="${filters#,}" declare -a build_filters=() @@ -43,10 +43,10 @@ if [[ -n "$filters" ]]; then test_filters=( "--test_tag_filters=$filters" ) fi -# Apps are sample programs and are only meant to run on Linux. +# The apps are sample programs and are only meant to run on Linux. if [[ "$OSTYPE" == "linux-gnu"* ]]; then - bazel build "${build_filters[@]}" --config=sse "$@" apps:all bazel build "${build_filters[@]}" "$@" apps:all + bazel build "$@" apps:all fi # Run all basic tests. This should work on all platforms. From 40c0bf2e52f36e74690079653cddd44f2b6f1703 Mon Sep 17 00:00:00 2001 From: mhucka Date: Wed, 18 Jun 2025 18:14:46 +0000 Subject: [PATCH 2/6] Correct the default Bazel vector instructions options The documented way that `bazel build`, `bazel test`, and similar commands behave without options like `--config=avx` is that the AVX, SSE, and other optimization options are not applied. However, this was not what was happening: the default ended up applying them. The previous changes to `.bazelrc` and `dev_tools/test_libs.sh` that I did in PR #758 and other recent PRs not fully address this. The changes here invert the way `--build_tag_filters` and `--test_tag_filters` are used: they are set to filter out things tagged with `avx` and `sse` by default in `.bazelrc`, and options like `--config=sse` add the things back. To make this work, `dev_tools/test_libs.sh` has to be updated as well. --- .bazelrc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.bazelrc b/.bazelrc index 14f35e638..f9015db82 100644 --- a/.bazelrc +++ b/.bazelrc @@ -23,17 +23,17 @@ common --verbose_failures # Windows uses slightly different syntax. common --enable_platform_specific_config -build:linux --copt -std=c++17 -build:linux --cxxopt -std=c++17 +build:linux --copt=-std=c++17 +build:linux --cxxopt=-std=c++17 -build:macos --copt -std=c++17 -build:macos --cxxopt -std=c++17 +build:macos --copt=-std=c++17 +build:macos --cxxopt=-std=c++17 -build:windows --copt /std:c++17 -build:windows --cxxopt /std:c++17 +build:windows --copt=/std:c++17 +build:windows --cxxopt=/std:c++17 -build --copt -D_GLIBCXX_USE_CXX11_ABI=1 -build --cxxopt -D_GLIBCXX_USE_CXX11_ABI=1 +build --copt=-D_GLIBCXX_USE_CXX11_ABI=1 +build --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=1 # The default for vector instruction sets is to exclude them. # Config options later in this file can be layered to enable them. @@ -68,13 +68,13 @@ build:sanitizer --copt -fno-omit-frame-pointer # Address sanitizer build:asan --config=sanitizer -build:asan --copt -fsanitize=address -build:asan --linkopt=-fsanitize=address +build:asan --copt=-fsanitize=address +build:asan --linkopt -fsanitize=address # Memory sanitizer build:msan --config=sanitizer -build:msan --copt -fsanitize=leak -build:msan --linkopt=-fsanitize=leak +build:msan --copt=-fsanitize=leak +build:msan --linkopt -fsanitize=leak # No sanitizers build:nosan -- @@ -103,7 +103,7 @@ build:basic --copt -O3 # Build with OpenMP build:openmp --copt -fopenmp -build:openmp --linkopt=-lgomp +build:openmp --linkopt -lgomp # No OpenMP build:nopenmp -- @@ -112,7 +112,7 @@ build:nopenmp -- # ~~~~ Memory handler (choose one) ~~~~ # Build with tcmalloc -build:tcmalloc --linkopt="-ltcmalloc" +build:tcmalloc --linkopt -ltcmalloc # Build using malloc (default) build:malloc -- From 0ce15cf2c6db647175a819739a16b1e7670f2c70 Mon Sep 17 00:00:00 2001 From: mhucka Date: Wed, 18 Jun 2025 17:59:27 +0000 Subject: [PATCH 3/6] Update documentation about using bazel --- docs/bazel.md | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/docs/bazel.md b/docs/bazel.md index 990eb80a4..733847fef 100644 --- a/docs/bazel.md +++ b/docs/bazel.md @@ -1,39 +1,57 @@ # Building with Bazel -qsim provides [Bazel](https://github.com/bazelbuild/bazel) build rules for its -applications and tests. To build and run all tests using Bazel, run the -following command: +qsim provides [Bazel](https://github.com/bazelbuild/bazel) build and test rules +for qsim tests and sample applications. The Bazel targets are `tests` and +`apps`; you can combine these with the bazel commands `build`, `test`, and +`run` and configuration flags suitable for your computer hardware architecture +and software environment. + +On hardware and software platforms that support them, qsim can be configured to +take advantage of certain hardware optimizations, specifically AVX (a hardware +extension for optimizing vector arithmetic), SSE (streaming SIMD extensions), +and/or OpenMP (a software API for shared-memory parallel programming). By +default, the basic qsim build configuration does _not_ compile in support for +these features. (On some systems such as MacOS on Apple Silicon, they are not +available.) A basic build & test run is obtained using the following command: + +```shell +bazel test tests:all ``` -# AVX and OpenMP are recommended for best performance. -# See "Build configs" section below for more information. + +As an example of using optimization options, if your computer has support for +AVX and OpenMP, the following command will build and run all the tests with the +appropriate config options to make use of those features: + +```shell bazel test --config=avx --config=openmp tests:all ``` To run a sample simulation, use the command below. Note that this command -requires the circuit file to be specified both on the command line and in the -`data` field of the `qsim_base` BUILD rule. -``` +requires the `circuit_q24` file to be specified both on the command line and in +the `data` field of the `qsim_base` BUILD rule. + +```shell bazel run --config=avx --config=openmp apps:qsim_base -- -c circuits/circuit_q24 ``` ## Build configurations -Depending on the optimizers available on your machine, different config flags -(such as `--config=avx`, above) can be set to control which optimizers are -included in a given build or test run. +Depending on your computer's hardware architecture and the features available, +different Bazel config flags (such as `--config=avx`, above) can be used to +control which hardware optimizers are included in a given build or test run. ### Vector arithmetic optimizers Pick at most one of the following options: -``` +```bazel # Use AVX instructions for vector arithmetic. --config=avx # Use SSE instructions for vector arithmetic. --config=sse -# Do not use vector arithmetic optimization (default). +# Do not use vector arithmetic optimization (deault). --config=basic ``` @@ -41,7 +59,7 @@ Pick at most one of the following options: Pick at most one of the following options: -``` +```bazel # Use OpenMP to run operations in parallel when possible. --config=openmp @@ -51,14 +69,13 @@ Pick at most one of the following options: ### Memory allocators - [TCMalloc](https://github.com/google/tcmalloc) is a fast, multithreaded implementation of C's `malloc()` and C++'s `new` operator. It is an independent -open-source library developd by Google. TCMalloc can be used with qsim as an +open-source library developed by Google. TCMalloc can be used with qsim as an alternative to the default `malloc()`. Pick at most one of the following options: -``` +```bazel # Use TCMalloc for memory allocation. --config=tcmalloc From d2aa96730a5454bff6b7b9a0a859fd4c68c023f9 Mon Sep 17 00:00:00 2001 From: mhucka Date: Wed, 18 Jun 2025 21:23:54 +0000 Subject: [PATCH 4/6] Use = in option args more consistently It's not clear if it's essential to use =, but it seems more likely to avoid some argument-splitting issues, so let's use that consistently. --- .bazelrc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.bazelrc b/.bazelrc index f9015db82..fd4f6b3a8 100644 --- a/.bazelrc +++ b/.bazelrc @@ -63,18 +63,18 @@ test:verbose --test_summary=detailed # Shared config for sanitizers build:sanitizer --strip=never -build:sanitizer --copt -O1 -build:sanitizer --copt -fno-omit-frame-pointer +build:sanitizer --copt=-O1 +build:sanitizer --copt=-fno-omit-frame-pointer # Address sanitizer build:asan --config=sanitizer build:asan --copt=-fsanitize=address -build:asan --linkopt -fsanitize=address +build:asan --linkopt=-fsanitize=address # Memory sanitizer build:msan --config=sanitizer build:msan --copt=-fsanitize=leak -build:msan --linkopt -fsanitize=leak +build:msan --linkopt=-fsanitize=leak # No sanitizers build:nosan -- @@ -83,27 +83,27 @@ build:nosan -- # ~~~~ Instruction set options (choose one) ~~~~ # Build with AVX2 + FMA -build:avx --copt -O3 -build:avx --copt -mavx2 -build:avx --copt -mfma +build:avx --copt=-O3 +build:avx --copt=-mavx2 +build:avx --copt=-mfma build:avx --build_tag_filters=avx --ui_event_filters=-WARNING test:avx --test_tag_filters=avx --ui_event_filters=-WARNING # Build with SSE -build:sse --copt -O3 -build:sse --copt -msse4 +build:sse --copt=-O3 +build:sse --copt=-msse4 build:sse --build_tag_filters=sse --ui_event_filters=-WARNING test:sse --test_tag_filters=sse --ui_event_filters=-WARNING # Build without AVX or SSE -build:basic --copt -O3 +build:basic --copt=-O3 # ~~~~ Parallelization (choose one, or nopenmp for none) ~~~~ # Build with OpenMP -build:openmp --copt -fopenmp -build:openmp --linkopt -lgomp +build:openmp --copt=-fopenmp +build:openmp --linkopt=-lgomp # No OpenMP build:nopenmp -- @@ -112,7 +112,7 @@ build:nopenmp -- # ~~~~ Memory handler (choose one) ~~~~ # Build with tcmalloc -build:tcmalloc --linkopt -ltcmalloc +build:tcmalloc --linkopt=-ltcmalloc # Build using malloc (default) build:malloc -- From ca494ef770e2644126ab58fb36915599686cc5f1 Mon Sep 17 00:00:00 2001 From: mhucka Date: Wed, 18 Jun 2025 21:37:28 +0000 Subject: [PATCH 5/6] Remove build_filters from bazel test invocation --- dev_tools/test_libs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/test_libs.sh b/dev_tools/test_libs.sh index 58fc54289..1cd833c56 100755 --- a/dev_tools/test_libs.sh +++ b/dev_tools/test_libs.sh @@ -50,4 +50,4 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then fi # Run all basic tests. This should work on all platforms. -bazel test "${build_filters[@]}" "${test_filters[@]}" "$@" tests:all +bazel test "${test_filters[@]}" "$@" tests:all From 3852481ddf33803e285dc22d0456a148c2b19858 Mon Sep 17 00:00:00 2001 From: mhucka Date: Wed, 18 Jun 2025 21:41:54 +0000 Subject: [PATCH 6/6] Remove unnecessary second bazel build of apps On lines 48-49: if the first bazel build invocation succeeds, then the second is pointless because it's _more_ likely to succeed than the first. If the first invocation fails, we won't get to the second one anyway. --- dev_tools/test_libs.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dev_tools/test_libs.sh b/dev_tools/test_libs.sh index 1cd833c56..9c8fb604a 100755 --- a/dev_tools/test_libs.sh +++ b/dev_tools/test_libs.sh @@ -46,7 +46,6 @@ fi # The apps are sample programs and are only meant to run on Linux. if [[ "$OSTYPE" == "linux-gnu"* ]]; then bazel build "${build_filters[@]}" "$@" apps:all - bazel build "$@" apps:all fi # Run all basic tests. This should work on all platforms.