├── .clang-format ├── .dockerignore ├── .gitignore ├── .gitlab-ci.yml ├── .gitlab ├── custom-jobs-and-variables.yml ├── jobs │ ├── corona.yml │ ├── lassen.yml │ ├── poodle.yml │ ├── ruby.yml │ └── tioga.yml └── subscribed-pipelines.yml ├── .gitmodules ├── .mailmap ├── .uberenv_config.json ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── COPYRIGHT ├── Dockerfile ├── LICENSE ├── NOTICE ├── README.md ├── RELEASE_NOTES.md ├── azure-pipelines.yml ├── benchmarks ├── CMakeLists.txt ├── chai_arraymanager_benchmarks.cpp ├── chai_benchmark_utils.hpp ├── chai_managed_ptr_benchmarks.cpp └── chai_managedarray_benchmarks.cpp ├── cmake ├── ChaiBasics.cmake ├── SetupChaiOptions.cmake ├── chai-config.cmake.in └── thirdparty │ └── SetupChaiThirdparty.cmake ├── docs ├── CMakeLists.txt ├── doxygen │ ├── CMakeLists.txt │ └── Doxyfile.in └── sphinx │ ├── CMakeLists.txt │ ├── advanced_configuration.rst │ ├── code_documentation.rst │ ├── conf.py │ ├── conf.py.in │ ├── contribution_guide.rst │ ├── developer │ ├── ci.rst │ └── uberenv.rst │ ├── developer_guide.rst │ ├── getting_started.rst │ ├── index.rst │ ├── tutorial.rst │ └── user_guide.rst ├── examples ├── CMakeLists.txt ├── chai-umpire-allocators.cpp ├── ex1.cpp ├── example.cpp ├── managed_ptr_example.cpp └── pinned.cpp ├── host-configs └── lc │ ├── blueos_3_ppc64le_ib_p9 │ └── nvcc_clang.cmake │ ├── toss_4_x86_64_ib │ ├── clang.cmake │ └── intel.cmake │ └── toss_4_x86_64_ib_cray │ ├── amdclang-xnack.cmake │ └── amdclang.cmake ├── reproducers ├── CMakeLists.txt ├── managed_ptr_multiple_inheritance_reproducer.cpp ├── managed_ptr_reproducer.cpp ├── virtual_function_complex_reproducer.cpp └── virtual_function_simple_reproducer.cpp ├── scripts ├── apply-license-info.sh ├── check-license-info.sh ├── format-source.sh ├── gitlab │ └── build_and_test.sh ├── license.txt ├── make_release_tarball.sh ├── travis │ ├── build_and_test.sh │ └── install_llvm.sh └── update-copyright.sh ├── src ├── CMakeLists.txt ├── chai │ ├── ArrayManager.cpp │ ├── ArrayManager.hpp │ ├── ArrayManager.inl │ ├── CMakeLists.txt │ ├── ChaiMacros.hpp │ ├── ExecutionSpaces.hpp │ ├── ManagedArray.hpp │ ├── ManagedArray.inl │ ├── ManagedArrayView.hpp │ ├── ManagedArray_thin.inl │ ├── PointerRecord.hpp │ ├── RajaExecutionSpacePlugin.cpp │ ├── RajaExecutionSpacePlugin.hpp │ ├── Types.hpp │ ├── config.hpp.in │ ├── managed_array.hpp │ ├── managed_ptr.hpp │ └── pluginLinker.hpp └── util │ └── forall.hpp └── tests ├── CMakeLists.txt ├── install ├── CMakeLists.txt └── using-with-cmake │ ├── CMakeLists.txt │ ├── host-config.cmake.in │ └── using-with-cmake.cpp ├── integration ├── CMakeLists.txt ├── managed_array_tests.cpp ├── managed_ptr_tests.cpp ├── raja-chai-launch.cpp ├── raja-chai-nested.cpp └── raja-chai-tests.cpp └── unit ├── CMakeLists.txt ├── array_manager_unit_tests.cpp ├── managed_array_unit_tests.cpp └── managed_ptr_unit_tests.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle : google 2 | IndentWidth : 2 3 | BreakBeforeBraces : Linux 4 | KeepEmptyLinesAtTheStartOfBlocks : true 5 | MaxEmptyLinesToKeep : 2 6 | AccessModifierOffset : -2 7 | UseTab: Never 8 | AllowShortIfStatementsOnASingleLine : true 9 | ConstructorInitializerAllOnOneLineOrOnePerLine : true 10 | AllowShortFunctionsOnASingleLine : true 11 | AllowShortLoopsOnASingleLine : false 12 | BinPackParameters : false 13 | AllowAllParametersOfDeclarationOnNextLine : false 14 | AlignTrailingComments : true 15 | ColumnLimit : 80 16 | PenaltyBreakBeforeFirstCallParameter : 100 17 | PenaltyReturnTypeOnItsOwnLine : 65000 18 | PenaltyBreakString : 10 19 | 20 | # These improve formatting results but require clang 3.6/7 or higher 21 | BreakBeforeBinaryOperators : None 22 | AlignAfterOpenBracket: true 23 | BinPackArguments : false 24 | AlignOperands : true 25 | AlwaysBreakTemplateDeclarations : true 26 | Cpp11BracedListStyle : true 27 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | build* 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | install*/ 3 | .vscode/ 4 | *.swp 5 | *.swo 6 | Win32/chai.vcxproj.user 7 | Win32/.vs/ 8 | Win32/x64/ 9 | *.aps 10 | *.orig 11 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (MIT) 6 | ############################################################################### 7 | 8 | # DESCRIPTION: 9 | ############################################################################### 10 | # General GitLab pipelines configurations for supercomputers and Linux clusters 11 | # at Lawrence Livermore National Laboratory (LLNL). 12 | # This entire pipeline is LLNL-specific 13 | # 14 | # Important note: This file is a template provided by llnl/radiuss-shared-ci. 15 | # Remains to set variable values, change the reference to the radiuss-shared-ci 16 | # repo, opt-in and out optional features. The project can then extend it with 17 | # additional stages. 18 | # 19 | # In addition, each project should copy over and complete: 20 | # - .gitlab/custom-jobs-and-variables.yml 21 | # - .gitlab/subscribed-pipelines.yml 22 | # 23 | # The jobs should be specified in a file local to the project, 24 | # - .gitlab/jobs/${CI_MACHINE}.yml 25 | # or generated (see LLNL/Umpire for an example). 26 | ############################################################################### 27 | 28 | # We define the following GitLab pipeline variables: 29 | variables: 30 | ##### LC GITLAB CONFIGURATION 31 | # Use an LLNL service user to run CI. This prevents from running pipelines as an 32 | # actual user. 33 | LLNL_SERVICE_USER: umdev 34 | # Use the service user workspace. Solves permission issues, stores everything 35 | # at the same location whoever triggers a pipeline. 36 | CUSTOM_CI_BUILDS_DIR: /usr/workspace/umdev/gitlab-runner 37 | # Submodules: We don't need to fetch dependencies handled by Spack. 38 | GIT_SUBMODULE_STRATEGY: normal 39 | GIT_SUBMODULE_DEPTH: 1 40 | GIT_SUBMODULE_UPDATE_FLAGS: --jobs 2 41 | GIT_SUBMODULE_PATHS: scripts/radiuss-spack-configs scripts/uberenv 42 | 43 | ##### PROJECT VARIABLES 44 | # We build the projects in the CI clone directory (used in 45 | # script/gitlab/build_and_test.sh script). 46 | # TODO: add a clean-up mechanism. 47 | BUILD_ROOT: ${CI_PROJECT_DIR} 48 | 49 | ##### SHARED_CI CONFIGURATION 50 | # Required information about GitHub repository 51 | GITHUB_PROJECT_NAME: "CHAI" 52 | GITHUB_PROJECT_ORG: "LLNL" 53 | # Set the build-and-test command. 54 | # Nested variables are allowed and useful to customize the job command. We 55 | # prevent variable expansion so that you can define them at job level. 56 | JOB_CMD: 57 | value: "./scripts/gitlab/build_and_test.sh" 58 | expand: false 59 | # Override the pattern describing branches that will skip the "draft PR filter 60 | # test". Add protected branches here. See default value in 61 | # preliminary-ignore-draft-pr.yml. 62 | # ALWAYS_RUN_PATTERN: "" 63 | 64 | # We organize the build-and-test stage with sub-pipelines. Each sub-pipeline 65 | # corresponds to a test batch on a given machine. 66 | 67 | # High level stages 68 | stages: 69 | - prerequisites 70 | - build-and-test 71 | 72 | # Template for jobs triggering a build-and-test sub-pipeline: 73 | .build-and-test: 74 | stage: build-and-test 75 | trigger: 76 | include: 77 | - local: '.gitlab/custom-jobs-and-variables.yml' 78 | - project: 'radiuss/radiuss-shared-ci' 79 | ref: 'v2024.12.0' 80 | file: 'pipelines/${CI_MACHINE}.yml' 81 | - artifact: '${CI_MACHINE}-jobs.yml' 82 | job: 'generate-job-lists' 83 | strategy: depend 84 | forward: 85 | pipeline_variables: true 86 | 87 | include: 88 | - project: 'lc-templates/id_tokens' 89 | file: 'id_tokens.yml' 90 | # [Optional] checks preliminary to running the actual CI test 91 | #- project: 'radiuss/radiuss-shared-ci' 92 | # ref: 'v2024.12.0' 93 | # file: 'preliminary-ignore-draft-pr.yml' 94 | # pipelines subscribed by the project 95 | - local: '.gitlab/subscribed-pipelines.yml' 96 | -------------------------------------------------------------------------------- /.gitlab/custom-jobs-and-variables.yml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (MIT) 6 | ############################################################################### 7 | 8 | # We define the following GitLab pipeline variables: 9 | variables: 10 | # On LLNL's ruby, this pipeline creates only one allocation shared among jobs 11 | # in order to save time and resources. This allocation has to be uniquely named 12 | # so that we are sure to retrieve it and avoid collisions. 13 | ALLOC_NAME: ${CI_PROJECT_NAME}_ci_${CI_PIPELINE_ID} 14 | 15 | # Ruby 16 | # Arguments for top level allocation 17 | RUBY_SHARED_ALLOC: "--exclusive --reservation=ci --time=7 --nodes=1" 18 | # Arguments for job level allocation 19 | # Note: We repeat the reservation, necessary when jobs are manually re-triggered. 20 | RUBY_JOB_ALLOC: "--overlap --reservation=ci --nodes=1" 21 | # Project specific variants for ruby 22 | PROJECT_RUBY_VARIANTS: "~shared +raja tests=basic " 23 | # Project specific deps for ruby 24 | PROJECT_RUBY_DEPS: "^raja~examples~exercises " 25 | 26 | # Poodle 27 | # Arguments for top level allocation 28 | POODLE_SHARED_ALLOC: "--exclusive --partition=pdebug --time=7 --nodes=1" 29 | # Arguments for job level allocation 30 | # Note: We repeat the reservation, necessary when jobs are manually re-triggered. 31 | POODLE_JOB_ALLOC: "--overlap --nodes=1" 32 | # Project specific variants for poodle 33 | PROJECT_POODLE_VARIANTS: "~shared +raja tests=basic " 34 | # Project specific deps for poodle 35 | PROJECT_POODLE_DEPS: "^raja~examples~exercises " 36 | 37 | # Corona 38 | # Arguments for top level allocation 39 | CORONA_SHARED_ALLOC: "--exclusive --time-limit=9m --nodes=1" 40 | # Arguments for job level allocation 41 | CORONA_JOB_ALLOC: "--nodes=1 --begin-time=+5s" 42 | # Project specific variants for corona 43 | PROJECT_CORONA_VARIANTS: "~shared +raja tests=basic " 44 | # Project specific deps for corona 45 | PROJECT_CORONA_DEPS: "^raja~examples~exercises " 46 | 47 | # Tioga 48 | # Arguments for top level allocation 49 | TIOGA_SHARED_ALLOC: "--queue=pci --exclusive --time-limit=16m --nodes=1" 50 | # Arguments for job level allocation 51 | TIOGA_JOB_ALLOC: "--nodes=1 --begin-time=+5s" 52 | # Project specific variants for tioga 53 | PROJECT_TIOGA_VARIANTS: "~shared +raja tests=basic " 54 | # Project specific deps for tioga 55 | PROJECT_TIOGA_DEPS: "^raja~examples~exercises " 56 | 57 | # Lassen and Butte use a different job scheduler (spectrum lsf) that does not 58 | # allow pre-allocation the same way slurm does. 59 | # Arguments for job level allocation 60 | LASSEN_JOB_ALLOC: "1 -W 10 -q pci" 61 | # Project specific variants for lassen 62 | PROJECT_LASSEN_VARIANTS: "~shared +raja cuda_arch=70 tests=basic " 63 | # Project specific deps for lassen 64 | PROJECT_LASSEN_DEPS: "^raja~examples~exercises " 65 | 66 | # Configuration shared by build and test jobs specific to this project. 67 | # Not all configuration can be shared. Here projects can fine tune the 68 | # CI behavior. 69 | # See Umpire for an example (export junit test reports). 70 | .custom_job: 71 | artifacts: 72 | reports: 73 | junit: junit.xml 74 | name: "${CI_PROJECT_NAME}-${CI_MACHINE}-${CI_JOB_NAME}-${CI_PIPELINE_ID}" 75 | paths: 76 | - ./*.cmake 77 | 78 | .reproducer_vars: 79 | script: 80 | - | 81 | echo -e " 82 | # Required variables \n 83 | export MODULE_LIST=\"${MODULE_LIST}\" \n 84 | export SPEC=\"${SPEC//\"/\\\"}\" \n 85 | # Allow to set job script for debugging (only this differs from CI) \n 86 | export DEBUG_MODE=true \n 87 | # Using the CI build cache is optional and requires a token. Set it like so: \n 88 | # export REGISTRY_TOKEN=\"\" \n" 89 | -------------------------------------------------------------------------------- /.gitlab/jobs/corona.yml: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (MIT) 6 | ############################################################################## 7 | 8 | # Override reproducer section to define project specific variables. 9 | .corona_reproducer_vars: 10 | script: 11 | - !reference [.reproducer_vars, script] 12 | 13 | ######################## 14 | # Overridden shared jobs 15 | ######################## 16 | # We duplicate the shared jobs description and add necessary changes for this 17 | # project. We keep ${PROJECT__VARIANTS} and ${PROJECT__DEPS} 18 | # So that the comparison with the original job is easier. 19 | 20 | # No overridden jobs so far. 21 | 22 | ############ 23 | # Extra jobs 24 | ############ 25 | # We do not recommend using ${PROJECT__VARIANTS} and 26 | # ${PROJECT__DEPS} in the extra jobs. There is no reason not to fully 27 | # describe the spec here. 28 | -------------------------------------------------------------------------------- /.gitlab/jobs/lassen.yml: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (MIT) 6 | ############################################################################## 7 | 8 | # Override reproducer section to define project specific variables. 9 | .lassen_reproducer_vars: 10 | script: 11 | - !reference [.reproducer_vars, script] 12 | 13 | ######################## 14 | # Overridden shared jobs 15 | ######################## 16 | # We duplicate the shared jobs description and add necessary changes for this 17 | # project. We keep ${PROJECT__VARIANTS} and ${PROJECT__DEPS} 18 | # So that the comparison with the original job is easier. 19 | 20 | # Allow failure due to what appears to be a bug with handling std::function in 21 | # cuda context (https://github.com/LLNL/CHAI/pull/275#issuecomment-2332696091) 22 | gcc_11_2_1_cuda_11_8_0: 23 | variables: 24 | SPEC: "${PROJECT_LASSEN_VARIANTS} +cuda %gcc@=11.2.1 ^cuda@11.8.0+allow-unsupported-compilers ${PROJECT_LASSEN_DEPS}" 25 | MODULE_LIST: "cuda/11.8.0" 26 | extends: .job_on_lassen 27 | allow_failure: true 28 | 29 | ############ 30 | # Extra jobs 31 | ############ 32 | # We do not recommend using ${PROJECT__VARIANTS} and 33 | # ${PROJECT__DEPS} in the extra jobs. There is no reason not to fully 34 | # describe the spec here. 35 | 36 | clang_12_0_1_libcpp: 37 | extends: .job_on_lassen 38 | variables: 39 | SPEC: "~shared +raja tests=basic %clang@12.0.1 cflags==\"-DGTEST_HAS_CXXABI_H_=0\" cxxflags==\"-stdlib=libc++ -DGTEST_HAS_CXXABI_H_=0\" ^raja~examples~exercises" 40 | 41 | clang_16_0_6_libcpp: 42 | extends: .job_on_lassen 43 | variables: 44 | SPEC: "~shared +raja tests=basic %clang@16.0.6 cflags==\"-DGTEST_HAS_CXXABI_H_=0\" cxxflags==\"-stdlib=libc++ -DGTEST_HAS_CXXABI_H_=0\" ^raja~examples~exercises" 45 | 46 | clang_12_0_1_gcc_8_3_1_memleak: 47 | extends: .job_on_lassen 48 | variables: 49 | SPEC: "~shared +raja tests=basic %clang@12.0.1.gcc.8.3.1 cxxflags==\"-fsanitize=address\" ^raja~examples~exercises" 50 | ASAN_OPTIONS: "detect_leaks=1" 51 | 52 | clang_16_0_6_gcc_8_3_1_memleak: 53 | extends: .job_on_lassen 54 | variables: 55 | SPEC: "~shared +raja tests=basic %clang@16.0.6.gcc.8.3.1 cxxflags==\"-fsanitize=address\" ^raja~examples~exercises" 56 | ASAN_OPTIONS: "detect_leaks=1" 57 | 58 | clang_12_0_1_datarace: 59 | extends: .job_on_lassen 60 | variables: 61 | SPEC: "~shared +raja tests=basic %clang@12.0.1 cxxflags==\"-fsanitize=thread\" ^raja~examples~exercises" 62 | 63 | clang_16_0_6_datarace: 64 | extends: .job_on_lassen 65 | variables: 66 | SPEC: "~shared +raja tests=basic %clang@16.0.6 cxxflags==\"-fsanitize=thread\" ^raja~examples~exercises" 67 | 68 | -------------------------------------------------------------------------------- /.gitlab/jobs/poodle.yml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (MIT) 6 | ############################################################################### 7 | 8 | # Override reproducer section to define projet specific variables. 9 | .poodle_reproducer_vars: 10 | script: 11 | - !reference [.reproducer_vars, script] 12 | 13 | ######################## 14 | # Overridden shared jobs 15 | ######################## 16 | # We duplicate the shared jobs description and add necessary changes for this 17 | # project. We keep ${PROJECT__VARIANTS} and ${PROJECT__DEPS} 18 | # So that the comparison with the original job is easier. 19 | 20 | # No overridden jobs so far. 21 | 22 | ############ 23 | # Extra jobs 24 | ############ 25 | # We do not recommend using ${PROJECT__VARIANTS} and 26 | # ${PROJECT__DEPS} in the extra jobs. There is no reason not to fully 27 | # describe the spec here. 28 | 29 | clang_14_0_6_develop_tpls: 30 | variables: 31 | SPEC: " ~shared +raja tests=basic %clang@=14.0.6 ^umpire@develop ^raja@develop~examples~exercises ^camp@main" 32 | extends: .job_on_poodle 33 | allow_failure: true 34 | -------------------------------------------------------------------------------- /.gitlab/jobs/ruby.yml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (MIT) 6 | ############################################################################### 7 | 8 | # Override reproducer section to define project specific variables. 9 | .ruby_reproducer_vars: 10 | script: 11 | - !reference [.reproducer_vars, script] 12 | 13 | ######################## 14 | # Overridden shared jobs 15 | ######################## 16 | # We duplicate the shared jobs description and add necessary changes for this 17 | # project. We keep ${PROJECT__VARIANTS} and ${PROJECT__DEPS} 18 | # So that the comparison with the original job is easier. 19 | 20 | # No overridden jobs so far. 21 | 22 | ############ 23 | # Extra jobs 24 | ############ 25 | # We do not recommend using ${PROJECT__VARIANTS} and 26 | # ${PROJECT__DEPS} in the extra jobs. There is no reason not to fully 27 | # describe the spec here. 28 | 29 | clang_14_0_6_develop_tpls: 30 | variables: 31 | SPEC: " ~shared +raja tests=basic %clang@14.0.6 ^umpire@develop ^raja@develop~examples~exercises ^camp@main" 32 | extends: .job_on_ruby 33 | allow_failure: true 34 | -------------------------------------------------------------------------------- /.gitlab/jobs/tioga.yml: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (MIT) 6 | ############################################################################## 7 | 8 | # Override reproducer section to define project specific variables. 9 | .tioga_reproducer_vars: 10 | script: 11 | - !reference [.reproducer_vars, script] 12 | 13 | ######################## 14 | # Overridden shared jobs 15 | ######################## 16 | # We duplicate the shared jobs description and add necessary changes for this 17 | # project. We keep ${PROJECT__VARIANTS} and ${PROJECT__DEPS} 18 | # So that the comparison with the original job is easier. 19 | 20 | # No overridden jobs so far. 21 | 22 | ############ 23 | # Extra jobs 24 | ############ 25 | # We do not recommend using ${PROJECT__VARIANTS} and 26 | # ${PROJECT__DEPS} in the extra jobs. There is no reason not to fully 27 | # describe the spec here. 28 | -------------------------------------------------------------------------------- /.gitlab/subscribed-pipelines.yml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (MIT) 6 | ############################################################################### 7 | 8 | # The template job to test whether a machine is up. 9 | # Expects CI_MACHINE defined to machine name. 10 | .machine-check: 11 | stage: prerequisites 12 | tags: [shell, oslic] 13 | variables: 14 | GIT_STRATEGY: none 15 | script: 16 | - | 17 | if [[ $(jq '.[env.CI_MACHINE].total_nodes_up' /usr/global/tools/lorenz/data/loginnodeStatus) == 0 ]] 18 | then 19 | echo -e "\e[31mNo node available on ${CI_MACHINE}\e[0m" 20 | curl --url "https://api.github.com/repos/${GITHUB_PROJECT_ORG}/${GITHUB_PROJECT_NAME}/statuses/${CI_COMMIT_SHA}" \ 21 | --header 'Content-Type: application/json' \ 22 | --header "authorization: Bearer ${GITHUB_TOKEN}" \ 23 | --data "{ \"state\": \"failure\", \"target_url\": \"${CI_PIPELINE_URL}\", \"description\": \"GitLab ${CI_MACHINE} down\", \"context\": \"ci/gitlab/${CI_MACHINE}\" }" 24 | exit 1 25 | fi 26 | 27 | ### 28 | # Trigger a build-and-test pipeline for a machine. 29 | # Comment the jobs for machines you don’t need. 30 | ### 31 | 32 | # One job to generate the job list for all the subpipelines 33 | generate-job-lists: 34 | stage: prerequisites 35 | tags: [shell, oslic] 36 | variables: 37 | RADIUSS_JOBS_PATH: "scripts/radiuss-spack-configs/gitlab/radiuss-jobs" 38 | LOCAL_JOBS_PATH: ".gitlab/jobs" 39 | script: 40 | - cat ${RADIUSS_JOBS_PATH}/ruby.yml ${LOCAL_JOBS_PATH}/ruby.yml > ruby-jobs.yml 41 | - cat ${RADIUSS_JOBS_PATH}/poodle.yml ${LOCAL_JOBS_PATH}/poodle.yml > poodle-jobs.yml 42 | - cat ${RADIUSS_JOBS_PATH}/lassen.yml ${LOCAL_JOBS_PATH}/lassen.yml > lassen-jobs.yml 43 | - cat ${RADIUSS_JOBS_PATH}/corona.yml ${LOCAL_JOBS_PATH}/corona.yml > corona-jobs.yml 44 | - cat ${RADIUSS_JOBS_PATH}/tioga.yml ${LOCAL_JOBS_PATH}/tioga.yml > tioga-jobs.yml 45 | artifacts: 46 | paths: 47 | - ruby-jobs.yml 48 | - poodle-jobs.yml 49 | - lassen-jobs.yml 50 | - corona-jobs.yml 51 | - tioga-jobs.yml 52 | 53 | # RUBY 54 | ruby-up-check: 55 | variables: 56 | CI_MACHINE: "ruby" 57 | extends: [.machine-check] 58 | 59 | ruby-build-and-test: 60 | variables: 61 | CI_MACHINE: "ruby" 62 | needs: [ruby-up-check, generate-job-lists] 63 | extends: [.build-and-test] 64 | 65 | # POODLE 66 | poodle-up-check: 67 | variables: 68 | CI_MACHINE: "poodle" 69 | extends: [.machine-check] 70 | 71 | poodle-build-and-test: 72 | variables: 73 | CI_MACHINE: "poodle" 74 | needs: [poodle-up-check, generate-job-lists] 75 | extends: [.build-and-test] 76 | 77 | # CORONA 78 | corona-up-check: 79 | variables: 80 | CI_MACHINE: "corona" 81 | extends: [.machine-check] 82 | 83 | corona-build-and-test: 84 | variables: 85 | CI_MACHINE: "corona" 86 | needs: [corona-up-check, generate-job-lists] 87 | extends: [.build-and-test] 88 | 89 | # TIOGA 90 | tioga-up-check: 91 | variables: 92 | CI_MACHINE: "tioga" 93 | extends: [.machine-check] 94 | 95 | tioga-build-and-test: 96 | variables: 97 | CI_MACHINE: "tioga" 98 | needs: [tioga-up-check, generate-job-lists] 99 | extends: [.build-and-test] 100 | 101 | # LASSEN 102 | lassen-up-check: 103 | variables: 104 | CI_MACHINE: "lassen" 105 | extends: [.machine-check] 106 | 107 | lassen-build-and-test: 108 | variables: 109 | CI_MACHINE: "lassen" 110 | needs: [lassen-up-check, generate-job-lists] 111 | extends: [.build-and-test] 112 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "blt"] 2 | path = blt 3 | url = https://github.com/LLNL/blt.git 4 | [submodule "src/tpl/umpire"] 5 | path = src/tpl/umpire 6 | url = https://github.com/LLNL/Umpire.git 7 | [submodule "src/tpl/raja"] 8 | path = src/tpl/raja 9 | url = https://github.com/LLNL/RAJA.git 10 | [submodule "scripts/radiuss-spack-configs"] 11 | path = scripts/radiuss-spack-configs 12 | url = https://github.com/LLNL/radiuss-spack-configs 13 | [submodule "scripts/uberenv"] 14 | path = scripts/uberenv 15 | url = https://github.com/LLNL/uberenv.git 16 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | David Beckingsale David Alexander Beckingsale 2 | -------------------------------------------------------------------------------- /.uberenv_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "package_name" : "chai", 3 | "package_version" : "develop", 4 | "package_final_phase" : "initconfig", 5 | "package_source_dir" : "../..", 6 | "spack_url": "https://github.com/spack/spack.git", 7 | "spack_commit": "280017a9ba3f6a969743deca0eebc96e7c0e5cfd", 8 | "spack_configs_path": "scripts/radiuss-spack-configs", 9 | "spack_packages_path": "scripts/radiuss-spack-configs/packages", 10 | "spack_setup_clingo": false 11 | } 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | cmake_policy(SET CMP0057 NEW) 8 | cmake_policy(SET CMP0048 NEW) 9 | cmake_policy(SET CMP0025 NEW) 10 | 11 | include(CMakeDependentOption) 12 | include(CMakePackageConfigHelpers) 13 | 14 | project(Chai LANGUAGES C CXX VERSION 2025.03.0) 15 | cmake_minimum_required(VERSION 3.23) 16 | 17 | include(cmake/SetupChaiOptions.cmake) 18 | 19 | set(BLT_CXX_STD c++14 CACHE STRING "") 20 | 21 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "PGI") 22 | message(STATUS "Setting CMAKE_CXX_EXTENSIONS to ON for PGI Compiler") 23 | set( CMAKE_CXX_EXTENSIONS ON ) 24 | endif() 25 | 26 | message(STATUS "Using CMake version ${CMAKE_VERSION}") 27 | 28 | ################################ 29 | # BLT 30 | ################################ 31 | if (NOT BLT_LOADED) 32 | if (DEFINED BLT_SOURCE_DIR) 33 | if (NOT EXISTS ${BLT_SOURCE_DIR}/SetupBLT.cmake) 34 | message(FATAL_ERROR "Given BLT_SOURCE_DIR does not contain SetupBLT.cmake") 35 | endif() 36 | else () 37 | set (BLT_SOURCE_DIR ${PROJECT_SOURCE_DIR}/blt CACHE PATH "") 38 | 39 | if (NOT EXISTS ${BLT_SOURCE_DIR}/SetupBLT.cmake) 40 | message(FATAL_ERROR "\ 41 | The BLT submodule is not present. \ 42 | If in git repository run the following two commands:\n \ 43 | git submodule init\n \ 44 | git submodule update") 45 | endif () 46 | endif () 47 | 48 | include(${BLT_SOURCE_DIR}/SetupBLT.cmake) 49 | endif() 50 | 51 | ####################################### 52 | # Options that depend on BLT Options 53 | ####################################### 54 | cmake_dependent_option( CHAI_ENABLE_CUDA "Build CHAI with CUDA support" On 55 | "ENABLE_CUDA" Off ) 56 | cmake_dependent_option( CHAI_ENABLE_HIP "Build CHAI with HIP" On 57 | "ENABLE_HIP" Off ) 58 | cmake_dependent_option( CHAI_ENABLE_OPENMP "Build CHAI with OpenMP" On 59 | "ENABLE_OPENMP" Off ) 60 | cmake_dependent_option( CHAI_ENABLE_MPI "Build CHAI with MPI" On 61 | "ENABLE_MPI" Off ) 62 | 63 | cmake_dependent_option(CHAI_ENABLE_TESTS "Build CHAI tests" On 64 | "ENABLE_TESTS" Off) 65 | cmake_dependent_option(CHAI_ENABLE_BENCHMARKS "Build CHAI benchmarks" On 66 | "ENABLE_BENCHMARKS" Off) 67 | cmake_dependent_option(CHAI_ENABLE_EXAMPLES "Build CHAI examples" On 68 | "ENABLE_EXAMPLES" Off ) 69 | 70 | cmake_dependent_option(CHAI_ENABLE_DOCS "Build CHAI docs" On 71 | "ENABLE_DOCS" Off) 72 | cmake_dependent_option( CHAI_ENABLE_GMOCK "Build CHAI with gmock" On 73 | "ENABLE_GMOCK" Off ) 74 | 75 | include(cmake/ChaiBasics.cmake) 76 | 77 | add_subdirectory(src) 78 | 79 | if (CHAI_ENABLE_TESTS) 80 | add_subdirectory(tests) 81 | endif() 82 | 83 | if (CHAI_ENABLE_BENCHMARKS) 84 | add_subdirectory(benchmarks) 85 | endif() 86 | 87 | if (CHAI_ENABLE_EXAMPLES) 88 | add_subdirectory(examples) 89 | endif() 90 | 91 | if (CHAI_ENABLE_DOCS) 92 | add_subdirectory(docs) 93 | endif() 94 | 95 | if (CHAI_ENABLE_REPRODUCERS) 96 | add_subdirectory(reproducers) 97 | endif() 98 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at chai-dev@llnl.gov. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to CHAI 2 | 3 | This document is intented for developers who want to add new features or 4 | bugfixes to CHAI. It assumes you have some familiarity with git and GitHub. It 5 | will discuss what a good pull request (PR) looks like, and the tests that your 6 | PR must pass before it can be merged into CHAI. 7 | 8 | ## Forking CHAI 9 | 10 | If you aren't a CHAI deveolper at LLNL, then you won't have permission to push 11 | new branches to the repository. First, you should create a 12 | [fork](https://github.com/LLNL/CHAI#fork-destination-box). This will create a 13 | copy of the CHAI repository that you own, and will ensure you can push your 14 | changes up to GitHub and create pull requests. 15 | 16 | ## Developing a New Feature 17 | 18 | New features should be based on the `develop` branch. When you want to create a 19 | new feature, first ensure you have an up-to-date copy of the `develop` branch: 20 | 21 | $ git checkout develop 22 | $ git pull origin develop 23 | 24 | You can now create a new branch to develop your feature on: 25 | 26 | $ git checkout -b feature/ 27 | 28 | Proceed to develop your feature on this branch, and add tests that will exercise 29 | your new code. If you are creating new methods or classes, please add Doxygen 30 | documentation. 31 | 32 | Once your feature is complete and your tests are passing, you can push your 33 | branch to GitHub and create a PR. 34 | 35 | ## Developing a Bug Fix 36 | 37 | First, check if the change you want to make has been fixed in `develop`. If so, 38 | we suggest you either start using the `develop` branch, or temporarily apply the 39 | fix to whichever version of CHAI you are using. 40 | 41 | Assuming there is an unsolved bug, first make sure you have an up-to-date copy 42 | of the develop branch: 43 | 44 | $ git checkout develop 45 | $ git pull origin develop 46 | 47 | Then create a new branch for your bugfix: 48 | 49 | $ git checkout -b bugfix/ 50 | 51 | First, add a test that reproduces the bug you have found. Then develop your 52 | bugfix as normal, and ensure to `make test` to check your changes actually fix 53 | the bug. 54 | 55 | Once you are finished, you can push your branch to GitHub, then create a PR. 56 | 57 | ## Creating a Pull Request 58 | 59 | You can create a new PR [here](https://github.com/LLNL/CHAI/compare). GitHub 60 | has a good [guide](https://help.github.com/articles/about-pull-requests/) to PR 61 | basics if you want some more information. Ensure that your PR base is the 62 | `develop` branch of CHAI. 63 | 64 | Add a descriptive title explaining the bug you fixed or the feature you have 65 | added, and put a longer description of the changes you have made in the comment 66 | box. 67 | 68 | Once your PR has been created, it will be run through our automated tests and 69 | also be reviewed by RAJA team members. Providing the branch passes both the 70 | tests and reviews, it will be merged into RAJA. 71 | 72 | ## Tests 73 | 74 | CHAI's tests are all in the `test` directory, and your PR must pass all these tests 75 | before it is merged. If you are adding a new feature, add new tests. 76 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Intellectual Property Notice 2 | ------------------------------ 3 | 4 | CHAI is licensed under the BSD 3 Clause license (LICENSE or 5 | https://opensource.org/licenses/BSD-3-Clause). 6 | 7 | Copyrights and patents in the CHAI project are retained by contributors. No 8 | copyright assignment is required to contribute to CHAI. 9 | 10 | SPDX usage 11 | ------------ 12 | 13 | Individual files contain SPDX tags instead of the full license text. 14 | This enables machine processing of license information based on the SPDX 15 | License Identifiers that are available here: https://spdx.org/licenses/ 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/llnl/radiuss:ubuntu-22.04-gcc-13 AS gcc 2 | ENV GTEST_COLOR=1 3 | COPY . /home/chai/workspace 4 | WORKDIR /home/chai/workspace/build 5 | RUN cmake -DENABLE_COVERAGE=On -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc .. && \ 6 | make -j 16 && \ 7 | ctest -T test --output-on-failure 8 | 9 | FROM ghcr.io/llnl/radiuss:clang-15-ubuntu-22.04 AS clang 10 | ENV GTEST_COLOR=1 11 | COPY . /home/chai/workspace 12 | WORKDIR /home/chai/workspace/build 13 | RUN cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang .. && \ 14 | make -j 16 && \ 15 | ctest -T test --output-on-failure 16 | 17 | FROM ghcr.io/llnl/radiuss:intel-2024.0-ubuntu-20.04 AS intel 18 | ENV GTEST_COLOR=1 19 | COPY . /home/chai/workspace 20 | WORKDIR /home/chai/workspace/build 21 | RUN /bin/bash -c "source /opt/intel/oneapi/setvars.sh 2>&1 > /dev/null && \ 22 | cmake -DCMAKE_CXX_COMPILER=icpx -DCMAKE_C_COMPILER=icx -DENABLE_WARNINGS_AS_ERRORS=Off .. && \ 23 | make -j 16 && \ 24 | ctest -T test --output-on-failure" 25 | 26 | FROM ghcr.io/llnl/radiuss:ubuntu-22.04-cuda-12-3 AS cuda 27 | ENV GTEST_COLOR=1 28 | COPY . /home/chai/workspace 29 | WORKDIR /home/chai/workspace/build 30 | RUN cmake -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc -DENABLE_CUDA=On -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc -DCMAKE_CUDA_ARCHITECTURES=70 .. && \ 31 | make -j 16 32 | 33 | # TODO: switch to ROCM 6 34 | FROM ghcr.io/llnl/radiuss:hip-5.6.1-ubuntu-20.04 AS hip 35 | ENV GTEST_COLOR=1 36 | ENV HCC_AMDGPU_TARGET=gfx900 37 | COPY . /home/chai/workspace 38 | WORKDIR /home/chai/workspace/build 39 | RUN cmake -DCMAKE_CXX_COMPILER=amdclang++ -DCMAKE_C_COMPILER=amdclang -DENABLE_HIP=On -DENABLE_WARNINGS_AS_ERRORS=Off .. && \ 40 | make -j 16 41 | 42 | FROM ghcr.io/llnl/radiuss:intel-2024.0-ubuntu-20.04 AS sycl 43 | ENV GTEST_COLOR=1 44 | COPY . /home/chai/workspace 45 | WORKDIR /home/chai/workspace/build 46 | RUN /bin/bash -c "source /opt/intel/oneapi/setvars.sh 2>&1 > /dev/null && \ 47 | cmake -DCMAKE_CXX_COMPILER=dpcpp -DCMAKE_C_COMPILER=icx -DENABLE_WARNINGS_AS_ERRORS=Off .. && \ 48 | make -j 16" 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-25, Lawrence Livermore National Security, LLC. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the copyright holder nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This work was produced under the auspices of the U.S. Department of Energy by 2 | Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. 3 | 4 | This work was prepared as an account of work sponsored by an agency of the 5 | United States Government. Neither the United States Government nor Lawrence 6 | Livermore National Security, LLC, nor any of their employees makes any warranty, 7 | expressed or implied, or assumes any legal liability or responsibility for the 8 | accuracy, completeness, or usefulness of any information, apparatus, product, or 9 | process disclosed, or represents that its use would not infringe privately owned 10 | rights. Reference herein to any specific commercial product, process, or service 11 | by trade name, trademark, manufacturer, or otherwise does not necessarily 12 | constitute or imply its endorsement, recommendation, or favoring by the United 13 | States Government or Lawrence Livermore National Security, LLC. The views and 14 | opinions of authors expressed herein do not necessarily state or reflect those 15 | of the United States Government or Lawrence Livermore National Security, LLC, 16 | and shall not be used for advertising or product endorsement purposes. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [comment]: # (#################################################################) 2 | [comment]: # (Copyright 2016-25, Lawrence Livermore National Security, LLC) 3 | [comment]: # (and CHAI project contributors. See the CHAI LICENSE file for) 4 | [comment]: # (details.) 5 | [comment]: # 6 | [comment]: # (# SPDX-License-Identifier: BSD-3-Clause) 7 | [comment]: # (#################################################################) 8 | 9 | # CHAI v2025.03.0 10 | 11 | [![Azure Build Status](https://dev.azure.com/davidbeckingsale/CHAI/_apis/build/status/LLNL.CHAI?branchName=develop)](https://dev.azure.com/davidbeckingsale/CHAI/_build/latest?definitionId=2&branchName=develop) 12 | [![Build Status](https://travis-ci.org/LLNL/CHAI.svg?branch=develop)](https://travis-ci.org/LLNL/CHAI) 13 | [![Documentation Status](https://readthedocs.org/projects/chai/badge/?version=develop)](https://chai.readthedocs.io/en/develop/?badge=develop) 14 | 15 | 16 | CHAI is a library that handles automatic data migration to different memory 17 | spaces behind an array-style interface. It was designed to work with 18 | [RAJA](https://github.com/LLNL/RAJA) and integrates with it. CHAI could be 19 | used with other C++ abstractions, as well. 20 | 21 | CHAI uses CMake and BLT to handle builds. Make sure that you have a modern 22 | compiler loaded and the configuration is as simple as: 23 | 24 | $ git submodule update --init --recursive 25 | $ mkdir build && cd build 26 | $ cmake -DCUDA_TOOLKIT_ROOT_DIR=/path/to/cuda ../ 27 | 28 | CMake will provide output about which compiler is being used, and what version 29 | of CUDA was detected. Once CMake has completed, CHAI can be built with Make: 30 | 31 | $ make 32 | 33 | For more advanced configuration you can use standard CMake variables. 34 | 35 | More information is available in the [CHAI documentation](https://chai.readthedocs.io/en/develop/). 36 | 37 | ## Authors 38 | 39 | The original developers of CHAI are: 40 | 41 | - Holger Jones (jones19@llnl.gov) 42 | - David Poliakoff (poliakoff1@llnl.gov) 43 | - Peter Robinson (robinson96@llnl.gov) 44 | 45 | Contributors include: 46 | 47 | - David Beckingsale (david@llnl.gov) 48 | - Riyaz Haque (haque1@llnl.gov) 49 | - Adam Kunen (kunen1@llnl.gov) 50 | 51 | ## Release 52 | 53 | Copyright (c) 2016, Lawrence Livermore National Security, LLC. 54 | Produced at the Lawrence Livermore National Laboratory 55 | 56 | All rights reserved. 57 | 58 | Unlimited Open Source - BSD Distribution 59 | 60 | For release details and restrictions, please read the LICENSE file. 61 | It is also linked here: [LICENSE](./LICENSE) 62 | 63 | - `LLNL-CODE-705877` 64 | - `OCEC-16-189` 65 | -------------------------------------------------------------------------------- /RELEASE_NOTES.md: -------------------------------------------------------------------------------- 1 | [comment]: # (#################################################################) 2 | [comment]: # (Copyright 2016-24, Lawrence Livermore National Security, LLC) 3 | [comment]: # (and CHAI project contributors. See the CHAI LICENSE file for) 4 | [comment]: # (details.) 5 | [comment]: # 6 | [comment]: # (# SPDX-License-Identifier: BSD-3-Clause) 7 | [comment]: # (#################################################################) 8 | 9 | # CHAI Software Release Notes 10 | 11 | Notes describing significant changes in each CHAI release are documented 12 | in this file. 13 | 14 | The format of this file is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). 15 | 16 | ## [Unreleased] - Release date yyyy-mm-dd 17 | 18 | ### Changed 19 | - Use memcpy instead of umpire copy for CPU-only thin managed array realloc (allows tracking to be disabled). 20 | 21 | ### Fixed 22 | - Fixed ManagedArray::set when CHAI\_DISABLE\_RM=OFF and the initial space is not CPU. 23 | - Fixed memory leaks in ArrayManager. 24 | 25 | ## [Version 2025.03.0] - Release date 2025-03-19 26 | 27 | ### Added 28 | - Added a ManagedArray::clone function and deprecated chai::deepCopy. 29 | 30 | ### Fixed 31 | - Fixes reallocate when using pinned or unified memory. 32 | - Adds missing synchronize when using pinned memory. 33 | - Fixes possible hangs when evicting data. 34 | - Now respects allocators passed to ManagedArray constructors when CHAI\_DISABLE\_RM=TRUE. 35 | 36 | ### Removed 37 | - Removes deprecated ManagedArray::getPointer method. Use ManagedArray::data instead. 38 | - Removes ManagedArray::incr and ManagedArray::decr methods. Use ManagedArray::pick and ManagedArray::set instead. 39 | - Removes optional support for implicitly casting between raw pointers and ManagedArrays (CHAI\_ENABLE\_IMPLICIT\_CONVERSIONS). Use makeManagedArray and ManagedArray::data to perform explicit conversions instead. 40 | - Removes equality and inequality comparison operators between ManagedArrays and raw pointers. 41 | - Removes make\_managed\_from\_factory function for creating managed\_ptr objects from factory functions. This change will lead to safer adoption of allocators during construction and destruction of managed\_ptr objects. 42 | - Removes CHAI\_ENABLE\_PICK CMake option. ManagedArray::pick and ManagedArray::set will always be available. 43 | 44 | ## [Version 2024.07.0] - Release date 2024-07-26 45 | 46 | ### Changed 47 | - Updated to Umpire v2024.07.0 and RAJA v2024.07.0 48 | - Increased minimum CMake version required to 3.23 49 | - Turns off benchmarks and examples by default 50 | - Enable RAJA plugin by default 51 | 52 | ## [Version 2024.02.2] - Release date 2024-06-26 53 | 54 | ### Changed 55 | - Updated to RAJA v2024.02.2 56 | - Improved debugging with GPU simulation mode 57 | 58 | ## [Version 2024.02.1] - Release date 2024-04-19 59 | 60 | ### Changed 61 | - Updated to BLT v0.6.2, Umpire v2024.02.1, and RAJA v2024.02.1 62 | 63 | ## [Version 2024.02.0] - Release date 2024-03-04 64 | 65 | ### Added 66 | - Support for APUs with a single memory space. To use, configure with -DCHAI\_DISABLE\_RM=ON -DCHAI\_THIN\_GPU\_ALLOCATE=ON. 67 | 68 | ### Changed 69 | - Moved installed CMake targets from share/chai/cmake to lib/cmake/chai to be consistent with other libraries in the RAJA Portability Suite 70 | - Improved dependency handling during the build of CHAI and when it is imported into another library/application 71 | - Removed ArrayManager::enableDeviceSynchronization and ArrayManager::disableDeviceSynchronization. Instead, use the environment variables for device synchronization after all kernels (e.g. CUDA\_LAUNCH\_BLOCKING or HIP\_LAUNCH\_BLOCKING) 72 | 73 | ### Fixed 74 | - Use free instead of realloc when the size is 0 (fixes a warning from valgrind) 75 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: Docker 3 | timeoutInMinutes: 360 4 | strategy: 5 | matrix: 6 | gcc: 7 | docker_target: gcc 8 | clang: 9 | docker_target: clang 10 | #intel: 11 | #docker_target: intel 12 | #cuda: 13 | #docker_target: cuda 14 | #hip: 15 | #docker_target: hip 16 | #sycl: 17 | #docker_target: sycl 18 | pool: 19 | vmImage: 'ubuntu-latest' 20 | variables: 21 | DOCKER_BUILDKIT: '1' 22 | steps: 23 | - checkout: self 24 | clean: boolean 25 | submodules: recursive 26 | - task: Docker@1 27 | inputs: 28 | command: build 29 | dockerFile: 'Dockerfile' 30 | arguments: '--target $(docker_target)' 31 | - script: | 32 | CID=$(docker create llnl/chai:$(Build.BuildId)) 33 | echo ${CID} 34 | docker cp ${CID}:/home/chai/workspace/build local-build 35 | docker rm ${CID} 36 | displayName: 'Copy test artifacts' 37 | condition: ne( variables['docker_target'], 'nvcc') 38 | - task: PublishTestResults@2 39 | inputs: 40 | testResultsFormat: 'cTest' 41 | testResultsFiles: '**/Test.xml' 42 | testRunTitle: '$(docker_target) Tests' 43 | condition: ne( variables['docker_target'], 'nvcc') 44 | -------------------------------------------------------------------------------- /benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | set (chai_benchmark_depends 8 | chai 9 | gbenchmark) 10 | 11 | if (CHAI_ENABLE_CUDA) 12 | set (chai_benchmark_depends 13 | ${chai_benchmark_depends} 14 | cuda) 15 | endif () 16 | 17 | if (CHAI_ENABLE_HIP) 18 | set (chai_benchmark_depends 19 | ${chai_benchmark_depends} 20 | blt::hip) 21 | endif () 22 | 23 | blt_add_executable( 24 | NAME arraymanager_benchmarks 25 | SOURCES chai_arraymanager_benchmarks.cpp 26 | DEPENDS_ON ${chai_benchmark_depends}) 27 | 28 | blt_add_benchmark( 29 | NAME arraymanager_benchmarks 30 | COMMAND arraymanager_benchmarks) 31 | 32 | blt_add_executable( 33 | NAME managedarray_benchmarks 34 | SOURCES chai_managedarray_benchmarks.cpp 35 | DEPENDS_ON ${chai_benchmark_depends}) 36 | 37 | blt_add_benchmark( 38 | NAME managedarray_benchmarks 39 | COMMAND managedarray_benchmarks) 40 | 41 | if (CHAI_ENABLE_MANAGED_PTR) 42 | blt_add_executable( 43 | NAME managed_ptr_benchmarks 44 | SOURCES chai_managed_ptr_benchmarks.cpp 45 | DEPENDS_ON ${chai_benchmark_depends}) 46 | 47 | blt_add_benchmark( 48 | NAME managed_ptr_benchmarks 49 | COMMAND managed_ptr_benchmarks) 50 | endif () 51 | -------------------------------------------------------------------------------- /benchmarks/chai_arraymanager_benchmarks.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include 8 | 9 | #include "benchmark/benchmark.h" 10 | 11 | #include "chai/ArrayManager.hpp" 12 | 13 | // void benchmark_arraymanager_alloc_default(benchmark::State& state) { 14 | // chai::ArrayManager* manager = chai::ArrayManager::getInstance(); 15 | // 16 | // while (state.KeepRunning()) { 17 | // void* ptr = manager->allocate(state.range(0)); 18 | // manager->free(ptr); 19 | // } 20 | // 21 | // state.SetItemsProcessed(state.iterations() * state.range(0)); 22 | // } 23 | // 24 | // void benchmark_arraymanager_alloc_cpu(benchmark::State& state) { 25 | // chai::ArrayManager* manager = chai::ArrayManager::getInstance(); 26 | // 27 | // while (state.KeepRunning()) { 28 | // void* ptr = manager->allocate(state.range(0), chai::CPU); 29 | // manager->free(ptr); 30 | // } 31 | // 32 | // state.SetItemsProcessed(state.iterations() * state.range(0)); 33 | // 34 | // } 35 | // 36 | // BENCHMARK(benchmark_arraymanager_alloc_default)->Range(1, INT_MAX); 37 | // BENCHMARK(benchmark_arraymanager_alloc_cpu)->Range(1, INT_MAX); 38 | // 39 | // #if defined(CHAI_ENABLE_CUDA) 40 | // void benchmark_arraymanager_alloc_gpu(benchmark::State& state) { 41 | // chai::ArrayManager* manager = chai::ArrayManager::getInstance(); 42 | // 43 | // while (state.KeepRunning()) { 44 | // void* ptr = manager->allocate(state.range(0), chai::GPU); 45 | // manager->free(ptr); 46 | // } 47 | // 48 | // state.SetItemsProcessed(state.iterations() * state.range(0)); 49 | // } 50 | // BENCHMARK(benchmark_arraymanager_alloc_gpu)->Range(1, INT_MAX); 51 | // #endif 52 | // 53 | BENCHMARK_MAIN(); 54 | -------------------------------------------------------------------------------- /benchmarks/chai_benchmark_utils.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_chai_benchmark_utils_HPP 8 | #define CHAI_chai_benchmark_utils_HPP 9 | 10 | #include "benchmark/benchmark_api.h" 11 | 12 | static void malloc_ranges(benchmark::internal::Benchmark* b) 13 | { 14 | // for (int i = 1; i <= (1<<30); i*=2) 15 | // b->Args(i); 16 | } 17 | 18 | #endif // CHAI_chai_benchmark_utils_HPP 19 | -------------------------------------------------------------------------------- /benchmarks/chai_managedarray_benchmarks.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include 8 | 9 | #include "benchmark/benchmark.h" 10 | 11 | #include "chai/ManagedArray.hpp" 12 | #include "chai/config.hpp" 13 | 14 | #include "../src/util/forall.hpp" 15 | 16 | void benchmark_managedarray_alloc_default(benchmark::State& state) 17 | { 18 | while (state.KeepRunning()) { 19 | chai::ManagedArray array(state.range(0)); 20 | array.free(); 21 | } 22 | 23 | state.SetItemsProcessed(state.iterations() * state.range(0)); 24 | } 25 | 26 | void benchmark_managedarray_alloc_cpu(benchmark::State& state) 27 | { 28 | while (state.KeepRunning()) { 29 | chai::ManagedArray array(state.range(0), chai::CPU); 30 | array.free(); 31 | } 32 | 33 | state.SetItemsProcessed(state.iterations() * state.range(0)); 34 | } 35 | 36 | BENCHMARK(benchmark_managedarray_alloc_default)->Range(1, INT_MAX); 37 | BENCHMARK(benchmark_managedarray_alloc_cpu)->Range(1, INT_MAX); 38 | 39 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 40 | void benchmark_managedarray_alloc_gpu(benchmark::State& state) 41 | { 42 | while (state.KeepRunning()) { 43 | chai::ManagedArray array(state.range(0), chai::GPU); 44 | array.free(); 45 | } 46 | 47 | state.SetItemsProcessed(state.iterations() * state.range(0)); 48 | } 49 | BENCHMARK(benchmark_managedarray_alloc_gpu)->Range(1, INT_MAX); 50 | #endif 51 | 52 | 53 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 54 | void benchmark_managedarray_move(benchmark::State& state) 55 | { 56 | chai::ManagedArray array(state.range(0)); 57 | 58 | forall(sequential(), 0, 1, [=](int i) { array[i] = 'b'; }); 59 | 60 | /* 61 | * Move data back and forth between CPU and GPU. 62 | * 63 | * Kernels just touch the data, but are still included in timing. 64 | */ 65 | while (state.KeepRunning()) { 66 | forall(gpu(), 0, 1, [=] __device__(int i) { array[i] = 'a'; }); 67 | 68 | forall(sequential(), 0, 1, [=](int i) { array[i] = 'b'; }); 69 | } 70 | 71 | array.free(); 72 | } 73 | 74 | BENCHMARK(benchmark_managedarray_move)->Range(1, INT_MAX); 75 | #endif 76 | 77 | BENCHMARK_MAIN(); 78 | -------------------------------------------------------------------------------- /cmake/ChaiBasics.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | set (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-extended-lambda") 8 | 9 | include(${PROJECT_SOURCE_DIR}/cmake/thirdparty/SetupChaiThirdparty.cmake) 10 | -------------------------------------------------------------------------------- /cmake/SetupChaiOptions.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################ 7 | option(CHAI_ENABLE_GPU_SIMULATION_MODE "Enable GPU Simulation Mode" Off) 8 | option(CHAI_ENABLE_OPENMP "Enable OpenMP" Off) 9 | option(CHAI_ENABLE_MPI "Enable MPI (for umpire replay only)" Off) 10 | 11 | option(CHAI_DISABLE_RM "Make ManagedArray a thin wrapper" Off) 12 | mark_as_advanced(CHAI_DISABLE_RM) 13 | 14 | option(CHAI_ENABLE_UM "Use CUDA unified (managed) memory" Off) 15 | option(CHAI_THIN_GPU_ALLOCATE "Single memory space model" Off) 16 | option(CHAI_ENABLE_PINNED "Use pinned host memory" Off) 17 | option(CHAI_ENABLE_RAJA_PLUGIN "Build plugin to set RAJA execution spaces" On) 18 | option(CHAI_ENABLE_GPU_ERROR_CHECKING "Enable GPU error checking" On) 19 | option(CHAI_ENABLE_MANAGED_PTR "Enable managed_ptr" On) 20 | option(CHAI_DEBUG "Enable Debug Logging." Off) 21 | option(CHAI_ENABLE_RAJA_NESTED_TEST "Enable raja-chai-nested-tests, which fails to build on Debug CUDA builds." On) 22 | option(CHAI_ENABLE_MANAGED_PTR_ON_GPU "Enable managed_ptr on GPU" On) 23 | 24 | option(CHAI_ENABLE_TESTS "Enable CHAI tests" On) 25 | option(CHAI_ENABLE_BENCHMARKS "Enable benchmarks" Off) 26 | option(CHAI_ENABLE_EXAMPLES "Enable CHAI examples" Off) 27 | option(CHAI_ENABLE_REPRODUCERS "Enable CHAI reproducers" Off) 28 | option(CHAI_ENABLE_DOCS "Enable CHAI documentation" Off) 29 | 30 | # options for Umpire as TPL 31 | set(ENABLE_GMOCK On CACHE BOOL "") 32 | option(CHAI_ENABLE_ASSERTS "Build Umpire with assert() enabled" On) 33 | set(ENABLE_GTEST_DEATH_TESTS ${CHAI_ENABLE_ASSERTS} CACHE BOOL "") 34 | 35 | option(CHAI_ENABLE_COPY_HEADERS "Enable CHAI copy headers" Off) 36 | 37 | set(ENABLE_CUDA Off CACHE BOOL "Enable CUDA") 38 | 39 | if (CHAI_ENABLE_UM AND NOT ENABLE_CUDA AND NOT CHAI_THIN_GPU_ALLOCATE) 40 | message(FATAL_ERROR "Option CHAI_ENABLE_UM requires ENABLE_CUDA or CHAI_THIN_GPU_ALLOCATE") 41 | endif() 42 | 43 | if (CHAI_THIN_GPU_ALLOCATE AND NOT CHAI_DISABLE_RM) 44 | message(FATAL_ERROR "Option CHAI_THIN_GPU_ALLOCATE requires CHAI_DISABLE_RM") 45 | endif() 46 | -------------------------------------------------------------------------------- /cmake/chai-config.cmake.in: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################ 7 | 8 | @PACKAGE_INIT@ 9 | 10 | # cache the prefix dir (could be overriden by find_dependency) 11 | set(CHAI_PACKAGE_PREFIX_DIR ${PACKAGE_PREFIX_DIR}) 12 | 13 | include(CMakeFindDependencyMacro) 14 | 15 | include("${CMAKE_CURRENT_LIST_DIR}/BLTSetupTargets.cmake") 16 | 17 | if (NOT TARGET umpire) 18 | find_dependency(umpire CONFIG NO_DEFAULT_PATH PATHS 19 | ${umpire_DIR} 20 | @umpire_DIR@ 21 | ${CHAI_PACKAGE_PREFIX_DIR}) 22 | endif () 23 | 24 | if (@CHAI_ENABLE_RAJA_PLUGIN@ AND NOT TARGET RAJA) 25 | find_dependency(raja CONFIG NO_DEFAULT_PATH PATHS 26 | ${raja_DIR} 27 | @raja_DIR@ 28 | ${CHAI_PACKAGE_PREFIX_DIR}) 29 | endif () 30 | 31 | include("${CMAKE_CURRENT_LIST_DIR}/chai-targets.cmake") 32 | 33 | check_required_components(chai) 34 | -------------------------------------------------------------------------------- /cmake/thirdparty/SetupChaiThirdparty.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | 8 | if (NOT TARGET umpire) 9 | if (DEFINED umpire_DIR OR DEFINED UMPIRE_DIR) 10 | message(STATUS "[CHAI] Using external Umpire") 11 | find_package(umpire CONFIG REQUIRED NO_DEFAULT_PATH PATHS ${umpire_DIR} ${UMPIRE_DIR}) 12 | else () 13 | if (NOT EXISTS ${PROJECT_SOURCE_DIR}/src/tpl/umpire/CMakeLists.txt) 14 | message(FATAL_ERROR "[CHAI] Umpire not found! Set umpire_DIR to the install location of Umpire or run 'git submodule update --init --recursive' in the CHAI repository, then try building again.") 15 | else () 16 | message(STATUS "[CHAI] Using internal Umpire") 17 | 18 | set(UMPIRE_ENABLE_BENCHMARKS Off CACHE BOOL "Enable benchmarks in Umpire") 19 | set(UMPIRE_ENABLE_C Off CACHE BOOL "Enable C in Umpire") 20 | set(UMPIRE_ENABLE_DOCS Off CACHE BOOL "Enable documentation in Umpire") 21 | set(UMPIRE_ENABLE_EXAMPLES Off CACHE BOOL "Enable examples in Umpire") 22 | set(UMPIRE_ENABLE_FORTRAN Off CACHE BOOL "Enable Fortran in Umpire") 23 | set(UMPIRE_ENABLE_TESTS Off CACHE BOOL "Enable tests in Umpire") 24 | set(UMPIRE_ENABLE_TOOLS Off CACHE BOOL "Enable tools in Umpire") 25 | 26 | add_subdirectory(${PROJECT_SOURCE_DIR}/src/tpl/umpire) 27 | endif () 28 | endif () 29 | endif () 30 | 31 | if (CHAI_ENABLE_RAJA_PLUGIN) 32 | if (NOT TARGET RAJA) 33 | if (DEFINED raja_DIR OR DEFINED RAJA_DIR) 34 | message(STATUS "[CHAI] Using external RAJA") 35 | find_package(raja CONFIG REQUIRED NO_DEFAULT_PATH PATHS ${raja_DIR} ${RAJA_DIR}) 36 | else () 37 | if (NOT EXISTS ${PROJECT_SOURCE_DIR}/src/tpl/raja/CMakeLists.txt) 38 | message(FATAL_ERROR "[CHAI] RAJA not found! Set raja_DIR to the install location of RAJA or run 'git submodule update --init --recursive' in the CHAI repository, then try building again.") 39 | else () 40 | message(STATUS "[CHAI] Using internal RAJA") 41 | set(RAJA_ENABLE_BENCHMARKS Off CACHE BOOL "Enable benchmarks in RAJA") 42 | set(RAJA_ENABLE_DOCS Off CACHE BOOL "Enable documentation in RAJA") 43 | set(RAJA_ENABLE_EXAMPLES Off CACHE BOOL "Enable examples in RAJA") 44 | set(RAJA_ENABLE_EXERCISES Off CACHE BOOL "Enable exercises in RAJA") 45 | set(RAJA_ENABLE_TESTS Off CACHE BOOL "Enable tests in RAJA") 46 | add_subdirectory(${PROJECT_SOURCE_DIR}/src/tpl/raja) 47 | endif () 48 | endif () 49 | endif () 50 | endif () 51 | -------------------------------------------------------------------------------- /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | if (DOXYGEN_FOUND) 8 | add_subdirectory(doxygen) 9 | endif () 10 | 11 | if (SPHINX_FOUND) 12 | set (SPHINX_HTML_THEME "import sphinx_rtd_theme\n 13 | html_theme = \"sphinx_rtd_theme\"\n 14 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]") 15 | 16 | add_subdirectory(sphinx) 17 | endif () 18 | -------------------------------------------------------------------------------- /docs/doxygen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | blt_add_doxygen_target(chai_doxgen) 8 | -------------------------------------------------------------------------------- /docs/sphinx/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | 8 | blt_add_sphinx_target(chai_docs) 9 | -------------------------------------------------------------------------------- /docs/sphinx/advanced_configuration.rst: -------------------------------------------------------------------------------- 1 | .. 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | .. _advanced_configuration: 8 | 9 | ================ 10 | Configuring CHAI 11 | ================ 12 | 13 | In addition to the normal options provided by CMake, CHAI uses some additional 14 | configuration arguments to control optional features and behavior. Each 15 | argument is a boolean option, and can be turned on or off: 16 | 17 | -DENABLE_CUDA=Off 18 | 19 | Here is a summary of the configuration options, their default value, and meaning: 20 | 21 | =========================== ======== =============================================================================== 22 | Variable Default Meaning 23 | =========================== ======== =============================================================================== 24 | ENABLE_CUDA Off Enable CUDA support. 25 | ENABLE_HIP Off Enable HIP support. 26 | CHAI_ENABLE_GPU_SIMULATION_MODE Off Simulates GPU execution. 27 | CHAI_ENABLE_UM Off Enable support for CUDA Unified Memory. 28 | CHAI_DISABLE_RM Off Disable the ArrayManager and make ManagedArray a thin wrapper around a pointer. 29 | ENABLE_TESTS On Build test executables. 30 | ENABLE_BENCHMARKS On Build benchmark programs. 31 | =========================== ======== =============================================================================== 32 | 33 | These arguments are explained in more detail below: 34 | 35 | * ENABLE_CUDA 36 | This option enables support for GPUs using CUDA. If CHAI is built without CUDA, HIP, or 37 | GPU_SIMULATION_MODE support, then only the ``CPU`` execution space is available for use. 38 | 39 | * ENABLE_HIP 40 | This option enables support for GPUs using HIP. If CHAI is built without CUDA, HIP, or 41 | GPU_SIMULATION_MODE support, then only the ``CPU`` execution space is available for use. 42 | 43 | * CHAI_ENABLE_GPU_SIMULATION_MODE 44 | This option simulates GPU support by enabling the GPU execution space, backed by a HOST 45 | umpire allocator. If CHAI is built without CUDA, HIP, or GPU_SIMULATION_MODE support, 46 | then only the ``CPU`` execution space is available for use. 47 | 48 | * CHAI_ENABLE_UM 49 | This option enables support for Unified Memory as an optional execution 50 | space. When a ``ManagedArray`` is allocated in the ``UM`` space, CHAI will 51 | not manually copy data. Data movement in this case is handled by the CUDA 52 | driver and runtime. 53 | 54 | * CHAI_DISABLE_RM 55 | This option will remove all usage of the ``ArrayManager`` class and let the 56 | ``ManagedArray`` objects function as thin wrappers around a raw pointer. This 57 | option can be used with CPU-only allocations, or with CUDA Unified Memory. 58 | 59 | * ENABLE_TESTS 60 | This option controls whether or not test executables will be built. 61 | 62 | * ENABLE_BENCHMARKS 63 | This option will build the benchmark programs used to test ``ManagedArray`` 64 | performance. 65 | 66 | -------------------------------------------------------------------------------- /docs/sphinx/code_documentation.rst: -------------------------------------------------------------------------------- 1 | .. 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | .. _code_documentation: 8 | 9 | ================== 10 | Code Documentation 11 | ================== 12 | -------------------------------------------------------------------------------- /docs/sphinx/conf.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | # -*- coding: utf-8 -*- 8 | 9 | # 10 | # CHAI documentation build configuration file, created by 11 | # sphinx-quickstart on Thu Mar 30 12:14:09 2017. 12 | # 13 | # This file is execfile()d with the current directory set to its 14 | # containing dir. 15 | # 16 | # Note that not all possible configuration values are present in this 17 | # autogenerated file. 18 | # 19 | # All configuration values have a default; values that are commented out 20 | # serve to show the default. 21 | 22 | # If extensions (or modules to document with autodoc) are in another directory, 23 | # add these directories to sys.path here. If the directory is relative to the 24 | # documentation root, use os.path.abspath to make it absolute, like shown here. 25 | # 26 | # import os 27 | # import sys 28 | # sys.path.insert(0, os.path.abspath('.')) 29 | 30 | 31 | # -- General configuration ------------------------------------------------ 32 | 33 | # If your documentation needs a minimal Sphinx version, state it here. 34 | # 35 | # needs_sphinx = '1.0' 36 | 37 | # Add any Sphinx extension module names here, as strings. They can be 38 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 39 | # ones. 40 | extensions = [] 41 | 42 | # Add any paths that contain templates here, relative to this directory. 43 | templates_path = ['_templates'] 44 | 45 | # The suffix(es) of source filenames. 46 | # You can specify multiple suffix as a list of string: 47 | # 48 | # source_suffix = ['.rst', '.md'] 49 | source_suffix = '.rst' 50 | 51 | # The master toctree document. 52 | master_doc = 'index' 53 | 54 | # General information about the project. 55 | project = u'CHAI' 56 | copyright = u'2016-2018, Lawrence Livermore National Security, LLC.' 57 | author = u'' 58 | 59 | # The version info for the project you're documenting, acts as replacement for 60 | # |version| and |release|, also used in various other places throughout the 61 | # built documents. 62 | # 63 | # The short X.Y version. 64 | version = u'2025.03' 65 | # The full version, including alpha/beta/rc tags. 66 | release = u'2025.03.0' 67 | 68 | # The language for content autogenerated by Sphinx. Refer to documentation 69 | # for a list of supported languages. 70 | # 71 | # This is also used if you do content translation via gettext catalogs. 72 | # Usually you set "language" from the command line for these cases. 73 | language = None 74 | 75 | # List of patterns, relative to source directory, that match files and 76 | # directories to ignore when looking for source files. 77 | # This patterns also effect to html_static_path and html_extra_path 78 | exclude_patterns = [] 79 | 80 | # The name of the Pygments (syntax highlighting) style to use. 81 | pygments_style = 'sphinx' 82 | 83 | # If true, `todo` and `todoList` produce output, else they produce nothing. 84 | todo_include_todos = False 85 | 86 | 87 | # -- Options for HTML output ---------------------------------------------- 88 | 89 | # The theme to use for HTML and HTML Help pages. See the documentation for 90 | # a list of builtin themes. 91 | # 92 | 93 | html_theme = 'default' 94 | 95 | # Theme options are theme-specific and customize the look and feel of a theme 96 | # further. For a list of options available for each theme, see the 97 | # documentation. 98 | # 99 | # html_theme_options = {} 100 | 101 | # Add any paths that contain custom static files (such as style sheets) here, 102 | # relative to this directory. They are copied after the builtin static files, 103 | # so a file named "default.css" will overwrite the builtin "default.css". 104 | html_static_path = ['_static'] 105 | 106 | 107 | # -- Options for HTMLHelp output ------------------------------------------ 108 | 109 | # Output file base name for HTML help builder. 110 | htmlhelp_basename = 'CHAIdoc' 111 | 112 | 113 | # -- Options for LaTeX output --------------------------------------------- 114 | 115 | latex_elements = { 116 | # The paper size ('letterpaper' or 'a4paper'). 117 | # 118 | # 'papersize': 'letterpaper', 119 | 120 | # The font size ('10pt', '11pt' or '12pt'). 121 | # 122 | # 'pointsize': '10pt', 123 | 124 | # Additional stuff for the LaTeX preamble. 125 | # 126 | # 'preamble': '', 127 | 128 | # Latex figure (float) alignment 129 | # 130 | # 'figure_align': 'htbp', 131 | } 132 | 133 | # Grouping the document tree into LaTeX files. List of tuples 134 | # (source start file, target name, title, 135 | # author, documentclass [howto, manual, or own class]). 136 | latex_documents = [ 137 | (master_doc, 'CHAI.tex', u'CHAI Documentation', 138 | u'CHAI Developers', 'manual'), 139 | ] 140 | 141 | 142 | # -- Options for manual page output --------------------------------------- 143 | 144 | # One entry per manual page. List of tuples 145 | # (source start file, name, description, authors, manual section). 146 | man_pages = [ 147 | (master_doc, 'chai', u'CHAI Documentation', 148 | [author], 1) 149 | ] 150 | 151 | 152 | # -- Options for Texinfo output ------------------------------------------- 153 | 154 | # Grouping the document tree into Texinfo files. List of tuples 155 | # (source start file, target name, title, author, 156 | # dir menu entry, description, category) 157 | texinfo_documents = [ 158 | (master_doc, 'CHAI', u'CHAI Documentation', 159 | author, 'CHAI', 'One line description of project.', 160 | 'Miscellaneous'), 161 | ] 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /docs/sphinx/conf.py.in: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | # -*- coding: utf-8 -*- 8 | # 9 | # CHAI documentation build configuration file, created by 10 | # sphinx-quickstart on Thu Mar 30 12:14:09 2017. 11 | # 12 | # This file is execfile()d with the current directory set to its 13 | # containing dir. 14 | # 15 | # Note that not all possible configuration values are present in this 16 | # autogenerated file. 17 | # 18 | # All configuration values have a default; values that are commented out 19 | # serve to show the default. 20 | 21 | # If extensions (or modules to document with autodoc) are in another directory, 22 | # add these directories to sys.path here. If the directory is relative to the 23 | # documentation root, use os.path.abspath to make it absolute, like shown here. 24 | # 25 | # import os 26 | # import sys 27 | # sys.path.insert(0, os.path.abspath('.')) 28 | 29 | 30 | # -- General configuration ------------------------------------------------ 31 | 32 | # If your documentation needs a minimal Sphinx version, state it here. 33 | # 34 | # needs_sphinx = '1.0' 35 | 36 | # Add any Sphinx extension module names here, as strings. They can be 37 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 38 | # ones. 39 | extensions = [] 40 | 41 | # Add any paths that contain templates here, relative to this directory. 42 | templates_path = ['_templates'] 43 | 44 | # The suffix(es) of source filenames. 45 | # You can specify multiple suffix as a list of string: 46 | # 47 | # source_suffix = ['.rst', '.md'] 48 | source_suffix = '.rst' 49 | 50 | # The master toctree document. 51 | master_doc = 'index' 52 | 53 | # General information about the project. 54 | project = u'CHAI' 55 | copyright = u'2016-2018, Lawrence Livermore National Security, LLC.' 56 | author = u'' 57 | 58 | # The version info for the project you're documenting, acts as replacement for 59 | # |version| and |release|, also used in various other places throughout the 60 | # built documents. 61 | # 62 | # The short X.Y version. 63 | version = u'2025.03' 64 | # The full version, including alpha/beta/rc tags. 65 | release = u'2025.03.0' 66 | 67 | # The language for content autogenerated by Sphinx. Refer to documentation 68 | # for a list of supported languages. 69 | # 70 | # This is also used if you do content translation via gettext catalogs. 71 | # Usually you set "language" from the command line for these cases. 72 | language = None 73 | 74 | # List of patterns, relative to source directory, that match files and 75 | # directories to ignore when looking for source files. 76 | # This patterns also effect to html_static_path and html_extra_path 77 | exclude_patterns = [] 78 | 79 | # The name of the Pygments (syntax highlighting) style to use. 80 | pygments_style = 'sphinx' 81 | 82 | # If true, `todo` and `todoList` produce output, else they produce nothing. 83 | todo_include_todos = False 84 | 85 | 86 | # -- Options for HTML output ---------------------------------------------- 87 | 88 | # The theme to use for HTML and HTML Help pages. See the documentation for 89 | # a list of builtin themes. 90 | # 91 | @SPHINX_HTML_THEME@ 92 | 93 | # Theme options are theme-specific and customize the look and feel of a theme 94 | # further. For a list of options available for each theme, see the 95 | # documentation. 96 | # 97 | # html_theme_options = {} 98 | 99 | # Add any paths that contain custom static files (such as style sheets) here, 100 | # relative to this directory. They are copied after the builtin static files, 101 | # so a file named "default.css" will overwrite the builtin "default.css". 102 | html_static_path = ['_static'] 103 | 104 | 105 | # -- Options for HTMLHelp output ------------------------------------------ 106 | 107 | # Output file base name for HTML help builder. 108 | htmlhelp_basename = 'CHAIdoc' 109 | 110 | 111 | # -- Options for LaTeX output --------------------------------------------- 112 | 113 | latex_elements = { 114 | # The paper size ('letterpaper' or 'a4paper'). 115 | # 116 | # 'papersize': 'letterpaper', 117 | 118 | # The font size ('10pt', '11pt' or '12pt'). 119 | # 120 | # 'pointsize': '10pt', 121 | 122 | # Additional stuff for the LaTeX preamble. 123 | # 124 | # 'preamble': '', 125 | 126 | # Latex figure (float) alignment 127 | # 128 | # 'figure_align': 'htbp', 129 | } 130 | 131 | # Grouping the document tree into LaTeX files. List of tuples 132 | # (source start file, target name, title, 133 | # author, documentclass [howto, manual, or own class]). 134 | latex_documents = [ 135 | (master_doc, 'CHAI.tex', u'CHAI Documentation', 136 | u'CHAI Developers', 'manual'), 137 | ] 138 | 139 | 140 | # -- Options for manual page output --------------------------------------- 141 | 142 | # One entry per manual page. List of tuples 143 | # (source start file, name, description, authors, manual section). 144 | man_pages = [ 145 | (master_doc, 'chai', u'CHAI Documentation', 146 | [author], 1) 147 | ] 148 | 149 | 150 | # -- Options for Texinfo output ------------------------------------------- 151 | 152 | # Grouping the document tree into Texinfo files. List of tuples 153 | # (source start file, target name, title, author, 154 | # dir menu entry, description, category) 155 | texinfo_documents = [ 156 | (master_doc, 'CHAI', u'CHAI Documentation', 157 | author, 'CHAI', 'One line description of project.', 158 | 'Miscellaneous'), 159 | ] 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /docs/sphinx/contribution_guide.rst: -------------------------------------------------------------------------------- 1 | .. 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | .. _contribution_guide: 8 | 9 | ================== 10 | Contribution Guide 11 | ================== 12 | 13 | This document is intented for developers who want to add new features or 14 | bugfixes to CHAI. It assumes you have some familiarity with git and GitHub. It 15 | will discuss what a good pull request (PR) looks like, and the tests that your 16 | PR must pass before it can be merged into CHAI. 17 | 18 | ------------ 19 | Forking CHAI 20 | ------------ 21 | 22 | If you aren't a CHAI deveolper at LLNL, then you won't have permission to push 23 | new branches to the repository. First, you should create a `fork 24 | `_. This will create a copy 25 | of the CHAI repository that you own, and will ensure you can push your changes 26 | up to GitHub and create pull requests. 27 | 28 | ------------------------ 29 | Developing a New Feature 30 | ------------------------ 31 | 32 | New features should be based on the ``develop`` branch. When you want to create 33 | a new feature, first ensure you have an up-to-date copy of the ``develop`` 34 | branch: 35 | 36 | .. code-block:: bash 37 | 38 | $ git checkout develop 39 | $ git pull origin develop 40 | 41 | You can now create a new branch to develop your feature on: 42 | 43 | .. code-block:: bash 44 | 45 | $ git checkout -b feature/ 46 | 47 | Proceed to develop your feature on this branch, and add tests that will exercise 48 | your new code. If you are creating new methods or classes, please add Doxygen 49 | documentation. 50 | 51 | Once your feature is complete and your tests are passing, you can push your 52 | branch to GitHub and create a PR. 53 | 54 | -------------------- 55 | Developing a Bug Fix 56 | -------------------- 57 | 58 | First, check if the change you want to make has been fixed in ``develop``. If 59 | so, we suggest you either start using the ``develop`` branch, or temporarily 60 | apply the fix to whichever version of CHAI you are using. 61 | 62 | Assuming there is an unsolved bug, first make sure you have an up-to-date copy 63 | of the develop branch: 64 | 65 | .. code-block:: bash 66 | 67 | $ git checkout develop 68 | $ git pull origin develop 69 | 70 | Then create a new branch for your bugfix: 71 | 72 | .. code-block:: bash 73 | 74 | $ git checkout -b bugfix/ 75 | 76 | First, add a test that reproduces the bug you have found. Then develop your 77 | bugfix as normal, and ensure to ``make test`` to check your changes actually 78 | fix the bug. 79 | 80 | Once you are finished, you can push your branch to GitHub, then create a PR. 81 | 82 | ----------------------- 83 | Creating a Pull Request 84 | ----------------------- 85 | 86 | You can create a new PR `here `_. GitHub 87 | has a good `guide `_ to 88 | PR basics if you want some more information. Ensure that your PR base is the 89 | ``develop`` branch of CHAI. 90 | 91 | Add a descriptive title explaining the bug you fixed or the feature you have 92 | added, and put a longer description of the changes you have made in the comment 93 | box. 94 | 95 | Once your PR has been created, it will be run through our automated tests and 96 | also be reviewed by RAJA team members. Providing the branch passes both the 97 | tests and reviews, it will be merged into RAJA. 98 | 99 | ----- 100 | Tests 101 | ----- 102 | 103 | CHAI's tests are all in the ``test`` directory, and your PR must pass all these 104 | tests before it is merged. If you are adding a new feature, add new tests. 105 | -------------------------------------------------------------------------------- /docs/sphinx/developer/ci.rst: -------------------------------------------------------------------------------- 1 | .. 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | .. _ci: 8 | 9 | ====================== 10 | Continuous Integration 11 | ====================== 12 | 13 | Gitlab CI 14 | --------- 15 | 16 | CHAI shares its Gitlab CI workflow with other projects. The documentation is 17 | therefore `shared`_. 18 | 19 | .. shared: /.cmake .. 89 | $ cmake --build -j . 90 | $ ctest --output-on-failure -T test 91 | 92 | It is also possible to use this configuration with the CI script outside of CI: 93 | 94 | .. code-block:: bash 95 | 96 | $ HOST_CONFIG=/.cmake scripts/gitlab/build_and_test.sh 97 | 98 | Testing new dependencies versions 99 | --------------------------------- 100 | 101 | CHAI depends on Umpire, and optionally CHAI. Testing with newer versions of both is made straightforward with Uberenv and Spack: 102 | 103 | * ``$ python scripts/uberenv/uberenv.py --spec=%clang@9.0.0 ^umpire@develop`` 104 | * ``$ python scripts/uberenv/uberenv.py --spec=%clang@9.0.0+raja ^raja@develop`` 105 | 106 | Those commands will install respectively `umpire@develop` and `raja@develop` locally, and generate host-config files with the corresponding paths. 107 | 108 | Again, the CI script can be used directly to install, build and test in one command: 109 | 110 | .. code-block:: bash 111 | 112 | $ SPEC="%clang@9.0.0 ^umpire@develop" scripts/gitlab/build_and_test.sh 113 | -------------------------------------------------------------------------------- /docs/sphinx/developer_guide.rst: -------------------------------------------------------------------------------- 1 | .. 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | .. _developer_guide: 8 | 9 | =============== 10 | Developer Guide 11 | =============== 12 | 13 | This section aims at gathering information useful to the developer. 14 | 15 | In particular, the local build scenarios as well as CI testing will be discussed here. 16 | 17 | .. toctree:: 18 | :maxdepth: 1 19 | 20 | developer/ci.rst 21 | developer/uberenv.rst 22 | -------------------------------------------------------------------------------- /docs/sphinx/getting_started.rst: -------------------------------------------------------------------------------- 1 | .. 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | .. _getting_started: 8 | 9 | =============== 10 | Getting Started 11 | =============== 12 | 13 | This page provides information on how to quickly get up and running with CHAI. 14 | 15 | ------------ 16 | Installation 17 | ------------ 18 | 19 | CHAI is hosted on GitHub `here `_. To clone the 20 | repo into your local working space, type: 21 | 22 | .. code-block:: bash 23 | 24 | $ git clone --recursive git@github.com:LLNL/CHAI.git 25 | 26 | 27 | The ``--recursive`` argument is required to ensure that the *BLT* submodule is 28 | also checked out. `BLT `_ is the build system we 29 | use for CHAI. 30 | 31 | 32 | ^^^^^^^^^^^^^ 33 | Building CHAI 34 | ^^^^^^^^^^^^^ 35 | 36 | CHAI uses CMake and BLT to handle builds. Make sure that you have a modern 37 | compiler loaded and the configuration is as simple as: 38 | 39 | .. code-block:: bash 40 | 41 | $ mkdir build && cd build 42 | $ cmake -DCUDA_TOOLKIT_ROOT_DIR=/path/to/cuda ../ 43 | 44 | By default, CHAI will attempt to build with CUDA. CMake will provide output 45 | about which compiler is being used, and what version of CUDA was detected. Once 46 | CMake has completed, CHAI can be built with Make: 47 | 48 | .. code-block:: bash 49 | 50 | $ make 51 | 52 | For more advanced configuration, see :doc:`advanced_configuration`. 53 | 54 | ----------- 55 | Basic Usage 56 | ----------- 57 | 58 | Let's take a quick tour through CHAI's most important features. A complete 59 | listing you can compile is included at the bottom of the page. First, let's 60 | create a new ManagedArray object. This is the interface through which you will 61 | want to access data: 62 | 63 | .. code-block:: cpp 64 | 65 | chai::ManagedArray a(100); 66 | 67 | This creates a ManagedArray storing elements of type double, with 100 elements 68 | allocated in the CPU memory. 69 | 70 | Next, let's assign some data to this array. We'll use CHAI's forall helper 71 | function for this, since it interacts with the ArrayManager for us to ensure 72 | the data is in the appropriate ExecutionSpace: 73 | 74 | .. code-block:: cpp 75 | 76 | forall(sequential(), 0, 100, [=] (int i) { 77 | a[i] = 3.14 * i; 78 | }); 79 | 80 | CHAI's ArrayManager can copy this array to another ExecutionSpace 81 | transparently. Let's use the GPU to double the contents of this array: 82 | 83 | .. code-block:: cpp 84 | 85 | forall(cuda(), 0, 100, [=] __device__ (int i) { 86 | a[i] = 2.0 * a[i]; 87 | }); 88 | 89 | We can access the array again on the CPU, and the ArrayManager will handle 90 | copying the modified data back: 91 | 92 | .. code-block:: cpp 93 | 94 | forall(sequential(), 0, 100, [=] (int i) { 95 | std::cout << "a[" << i << "] = " << a[i] << std::endl; 96 | }); 97 | 98 | -------------------------------------------------------------------------------- /docs/sphinx/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | ****** 8 | CHAI 9 | ****** 10 | 11 | CHAI is a C++ libary providing an array object that can be used transparently 12 | in multiple memory spaces. Data is automatically migrated based on 13 | copy-construction, allowing for correct data access regardless of location. 14 | CHAI can be used standalone, but is best when paired with the RAJA library, 15 | which has built-in CHAI integration that takes care of everything. 16 | 17 | - If you want to get and install CHAI, take a look at our getting started 18 | guide. 19 | - If you are looking for documentation about a particular CHAI function, see 20 | the code documentation. 21 | - Want to contribute? Take a look at our developer and contribution guides. 22 | 23 | Any questions? Contact chai-dev@llnl.gov 24 | 25 | .. toctree:: 26 | :maxdepth: 2 27 | :caption: Basics 28 | 29 | getting_started 30 | tutorial 31 | user_guide 32 | 33 | .. toctree:: 34 | :maxdepth: 2 35 | :caption: Reference 36 | 37 | advanced_configuration 38 | code_documentation 39 | 40 | .. toctree:: 41 | :maxdepth: 2 42 | :caption: Contributing 43 | 44 | contribution_guide 45 | developer_guide 46 | -------------------------------------------------------------------------------- /docs/sphinx/tutorial.rst: -------------------------------------------------------------------------------- 1 | .. 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | .. _tutorial: 8 | 9 | ======== 10 | Tutorial 11 | ======== 12 | 13 | The file ``src/examples/example.cpp`` contains a brief program that shows how 14 | CHAI can be used. Let's walk through this example, line-by-line: 15 | 16 | .. literalinclude:: ../../src/examples/example.cpp 17 | :language: c++ 18 | -------------------------------------------------------------------------------- /docs/sphinx/user_guide.rst: -------------------------------------------------------------------------------- 1 | .. 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | .. _user_guide: 8 | 9 | ********** 10 | User Guide 11 | ********** 12 | 13 | ----------------------------------- 14 | A Portable Pattern for Polymorphism 15 | ----------------------------------- 16 | 17 | CHAI provides a data structure to help handle cases where it is desirable to call virtual functions on the device. If you only call virtual functions on the host, this pattern is unnecessary. But for those who do want to use virtual functions on the device without a painstaking amount of refactoring, we begin with a short, albeit admittedly contrived example. 18 | 19 | .. code-block:: cpp 20 | 21 | class MyBaseClass { 22 | public: 23 | MyBaseClass() {} 24 | virtual ~MyBaseClass() {} 25 | virtual int getValue() const = 0; 26 | }; 27 | 28 | class MyDerivedClass : public MyBaseClass { 29 | public: 30 | MyDerivedClass(int value) : MyBaseClass(), m_value(value) {} 31 | ~MyDerivedClass() {} 32 | int getValue() const { return m_value; } 33 | 34 | private: 35 | int m_value; 36 | }; 37 | 38 | int main(int argc, char** argv) { 39 | MyBaseClass* myBaseClass = new MyDerivedClass(0); 40 | myBaseClass->getValue(); 41 | delete myBaseClass; 42 | return 0; 43 | } 44 | 45 | It is perfectly fine to call `myBaseClass->getValue()` in host code, since `myBaseClass` was created on the host. However, what if you want to call this virtual function on the device? 46 | 47 | .. code-block:: cpp 48 | 49 | __global__ void callVirtualFunction(MyBaseClass* myBaseClass) { 50 | myBaseClass->getValue(); 51 | } 52 | 53 | int main(int argc, char** argv) { 54 | MyBaseClass* myBaseClass = new MyDerivedClass(0); 55 | callVirtualFunction<<<1, 1>>>(myBaseClass); 56 | delete myBaseClass; 57 | return 0; 58 | } 59 | 60 | At best, calling this code will result in a crash. At worst, it will access garbage and happily continue while giving incorrect results. It is illegal to access host pointers on the device and produces undefined behavior. So what is our next attempt? Why not pass the argument by value rather than by a pointer? 61 | 62 | .. code-block:: cpp 63 | 64 | __global__ void callVirtualFunction(MyBaseClass myBaseClass) { 65 | myBaseClass.getValue(); 66 | } 67 | 68 | int main(int argc, char** argv) { 69 | MyBaseClass* myBaseClass = new MyDerivedClass(0); 70 | callVirtualFunction<<<1, 1>>>(*myBaseClass); // This will not compile 71 | delete myBaseClass; 72 | return 0; 73 | } 74 | 75 | At first glance, this may seem like it would work, but this is not supported by nvidia: "It is not allowed to pass as an argument to a `__global__` function an object of a class with virtual functions" (https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#virtual-functions). Also: "It is not allowed to pass as an argument to a `__global__` function an object of a class derived from virtual base classes" (https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#virtual-base-classes). You could refactor to use the curiously recurring template pattern, but that would likely require a large development effort and also limits the programming patterns you can use. Also, there is a limitation on the size of the arguments passed to a global kernel, so if you have a very large class this is simply impossible. So we make another attempt. 76 | 77 | .. code-block:: cpp 78 | 79 | __global__ void callVirtualFunction(MyBaseClass* myBaseClass) { 80 | myBaseClass->getValue(); 81 | } 82 | 83 | int main(int argc, char** argv) { 84 | MyBaseClass* myBaseClass = new MyDerivedClass(0); 85 | MyBaseClass* d_myBaseClass; 86 | cudaMalloc(&d_myBaseClass, sizeof(MyBaseClass)); 87 | cudaMemcpy(d_myBaseClass, myBaseClass, sizeof(MyBaseClass), cudaMemcpyHostToDevice); 88 | 89 | callVirtualFunction<<<1, 1>>>(d_myBaseClass); 90 | 91 | cudaFree(d_myBaseClass); 92 | delete myBaseClass; 93 | 94 | return 0; 95 | } 96 | 97 | We are getting nearer, but there is still a flaw. The bits of `myBaseClass` contain the virtual function table that allows virtual function lookups on the host, but that virtual function table is not valid for lookups on the device since it contains pointers to host functions. It will not work any better to cast to `MyDerivedClass` and copy the bits. The only option is to call the constructor on the device and keep that device pointer around. 98 | 99 | .. code-block:: cpp 100 | 101 | __global__ void make_on_device(MyBaseClass** myBaseClass, int argument) { 102 | *myBaseClass = new MyDerivedClass(argument); 103 | } 104 | 105 | __global__ void destroy_on_device(MyBaseClass* myBaseClass) { 106 | delete myBaseClass; 107 | } 108 | 109 | __global__ void callVirtualFunction(MyBaseClass* myBaseClass) { 110 | myBaseClass->getValue(); 111 | } 112 | 113 | int main(int argc, char** argv) { 114 | MyBaseClass** d_temp; 115 | cudaMalloc(&d_temp, sizeof(MyBaseClass*)); 116 | make_on_device<<<1, 1>>>(d_temp, 0); 117 | 118 | MyBaseClass** temp = (MyBaseClass**) malloc(sizeof(MyBaseClass*)); 119 | cudaMemcpy(temp, d_temp, sizeof(MyBaseClass*), cudaMemcpyDeviceToHost); 120 | MyBaseClass d_myBaseClass = *temp; 121 | 122 | callVirtualFunction<<<1, 1>>>(d_myBaseClass); 123 | 124 | free(temp); 125 | destroy_on_device<<<1, 1>>>(d_myBaseClass); 126 | cudaFree(d_temp); 127 | 128 | return 0; 129 | } 130 | 131 | OK, this is finally correct, but super tedious. So we took care of all the boilerplate and underlying details for you. The final result is at least recognizable when compared to the original code. The added benefit is that you can use a `chai::managed_ptr` on the host AND the device. 132 | 133 | .. code-block:: cpp 134 | 135 | __global__ void callVirtualFunction(chai::managed_ptr myBaseClass) { 136 | myBaseClass->getValue(); 137 | } 138 | 139 | int main(int argc, char** argv) { 140 | chai::managed_ptr myBaseClass = chai::make_managed(0); 141 | myBaseClass->getValue(); // Accessible on the host 142 | callVirtualFunction<<<1, 1>>>(myBaseClass); // Accessible on the device 143 | myBaseClass.free(); 144 | return 0; 145 | } 146 | 147 | OK, so we didn't do all the work for you, but we definitely gave you a leg up. What's left for you to do? You just need to make sure the functions accessed on the device have the `__device__` specifier (including constructors and destructors). We use the `CHAI_HOST_DEVICE` macro in this example, which actually annotates the functions as `__host__ __device__` so we can call the virtual method on both the host and the device. You also need to make sure the destructors of all base classes are virtual so the object gets cleaned up properly on the device. 148 | 149 | .. code-block:: cpp 150 | 151 | class MyBaseClass { 152 | public: 153 | CARE_HOST_DEVICE MyBaseClass() {} 154 | CARE_HOST_DEVICE virtual ~MyBaseClass() {} 155 | CARE_HOST_DEVICE virtual int getValue() const = 0; 156 | }; 157 | 158 | class MyDerivedClass : public MyBaseClass { 159 | public: 160 | CARE_HOST_DEVICE MyDerivedClass(int value) : MyBaseClass(), m_value(value) {} 161 | CARE_HOST_DEVICE ~MyDerivedClass() {} 162 | CARE_HOST_DEVICE int getValue() const { return m_value; } 163 | 164 | private: 165 | int m_value; 166 | }; 167 | 168 | Now you may rightfully ask, what happens when this class contains raw pointers? There is a convenient solution for this case and we demonstrate with a more interesting example. 169 | 170 | .. code-block:: cpp 171 | 172 | class MyBaseClass { 173 | public: 174 | CARE_HOST_DEVICE MyBaseClass() {} 175 | CARE_HOST_DEVICE virtual ~MyBaseClass() {} 176 | CARE_HOST_DEVICE virtual int getScalarValue() const = 0; 177 | CARE_HOST_DEVICE virtual int getArrayValue(int index) const = 0; 178 | }; 179 | 180 | class MyDerivedClass : public MyBaseClass { 181 | public: 182 | CARE_HOST_DEVICE MyDerivedClass(int scalarValue, int* arrayValue) 183 | : MyBaseClass(), m_scalarValue(scalarValue), m_arrayValue(arrayValue) {} 184 | CARE_HOST_DEVICE ~MyDerivedClass() {} 185 | CARE_HOST_DEVICE int getScalarValue() const { return m_scalarValue; } 186 | CARE_HOST_DEVICE int getArrayValue() const { return m_arrayValue; } 187 | 188 | private: 189 | int m_scalarValue; 190 | int* m_arrayValue; 191 | }; 192 | 193 | __global__ void callVirtualFunction(chai::managed_ptr myBaseClass) { 194 | int i = blockIdx.x*blockDim.x + threadIdx.x; 195 | myBaseClass->getScalarValue(); 196 | myBaseClass->getArrayValue(i); 197 | } 198 | 199 | int main(int argc, char** argv) { 200 | chai::ManagedArray arrayValue(10); 201 | chai::managed_ptr myBaseClass 202 | = chai::make_managed(0, chai::unpack(arrayValue)); 203 | callVirtualFunction<<<1, 10>>>(myBaseClass); 204 | myBaseClass.free(); 205 | arrayValue.free(); 206 | return 0; 207 | } 208 | 209 | The respective host and device pointers contained in the `chai::ManagedArray` can be extracted and passed to the host and device instance of `MyDerivedClass` using `chai::unpack`. Of course, if you never dereference `m_arrayValue` on the device, you could simply pass a raw pointer to `chai::make_managed`. If the class contains a `chai::ManagedArray`, a `chai::ManagedArray` can simply be passed to the constructor. The same rules apply for passing a `chai::managed_ptr`, calling `chai::unpack` on a `chai::managed_ptr`, or passing a raw pointer and not accessing it on the device. 210 | 211 | More complicated rules apply for keeping the data in sync between the host and device instances of an object, but it is possible to do so to a limited extent. It is also possible to control the lifetimes of objects passed to `chai::make_managed`. 212 | 213 | .. code-block:: cpp 214 | int main(int argc, char** argv) { 215 | chai::ManagedArray arrayValue(10); 216 | 217 | chai::managed_ptr myBaseClass 218 | = chai::make_managed(0, chai::unpack(arrayValue)); 219 | myBaseClass.set_callback([=] (chai::Action action, chai::ExecutionSpace space, void*) mutable { 220 | if (action == chai::ACTION_MOVE) { 221 | (void) chai::ManagedArray temp(arrayValue); // Copy constructor triggers movement 222 | } 223 | else if (action == chai::ACTION_FREE && space == chai::NONE) { 224 | temp.free(); 225 | } 226 | 227 | return false; 228 | }); 229 | 230 | callVirtualFunction<<<1, 10>>>(myBaseClass); 231 | myBaseClass.free(); 232 | // arrayValue.free(); // Not needed anymore 233 | return 0; 234 | } 235 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | set (chai_umpire_example_depends 8 | chai) 9 | 10 | if (CHAI_ENABLE_CUDA) 11 | set (chai_umpire_example_depends 12 | ${chai_umpire_example_depends} 13 | cuda) 14 | endif() 15 | if (CHAI_ENABLE_HIP) 16 | set (chai_umpire_example_depends 17 | ${chai_umpire_example_depends} 18 | blt::hip) 19 | endif() 20 | 21 | blt_add_executable( 22 | NAME chai-umpire-example.exe 23 | SOURCES chai-umpire-allocators.cpp 24 | DEPENDS_ON ${chai_umpire_example_depends}) 25 | 26 | if (CHAI_ENABLE_CUDA OR CHAI_ENABLE_HIP) 27 | blt_add_executable( 28 | NAME chai-example.exe 29 | SOURCES example.cpp 30 | DEPENDS_ON ${chai_umpire_example_depends}) 31 | 32 | blt_add_executable( 33 | NAME pinned.exe 34 | SOURCES pinned.cpp 35 | DEPENDS_ON ${chai_umpire_example_depends}) 36 | endif () 37 | 38 | if (CHAI_ENABLE_MANAGED_PTR) 39 | blt_add_executable( 40 | NAME managed_ptr_example.exe 41 | SOURCES managed_ptr_example.cpp 42 | DEPENDS_ON ${chai_umpire_example_depends}) 43 | endif () 44 | 45 | -------------------------------------------------------------------------------- /examples/chai-umpire-allocators.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "umpire/ResourceManager.hpp" 8 | #include "umpire/strategy/QuickPool.hpp" 9 | 10 | #include "chai/ManagedArray.hpp" 11 | #include "../src/util/forall.hpp" 12 | 13 | #include 14 | 15 | int main(int CHAI_UNUSED_ARG(argc), char** CHAI_UNUSED_ARG(argv)) 16 | { 17 | 18 | auto& rm = umpire::ResourceManager::getInstance(); 19 | 20 | auto cpu_pool = 21 | rm.makeAllocator("cpu_pool", 22 | rm.getAllocator("HOST")); 23 | 24 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 25 | auto gpu_pool = 26 | rm.makeAllocator("gpu_pool", 27 | rm.getAllocator("DEVICE")); 28 | #endif 29 | 30 | chai::ManagedArray array(100, 31 | std::initializer_list{chai::CPU 32 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 33 | , chai::GPU 34 | #endif 35 | }, 36 | std::initializer_list{cpu_pool 37 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 38 | , gpu_pool 39 | #endif 40 | }); 41 | 42 | forall(sequential(), 0, 100, [=](int i) { array[i] = 0.0f; }); 43 | 44 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 45 | forall(gpu(), 0, 100, [=] __device__(int i) { array[i] = 1.0f * i; }); 46 | #else 47 | forall(sequential(), 0, 100, [=] (int i) { array[i] = 1.0f * i; }); 48 | #endif 49 | 50 | forall(sequential(), 0, 100, [=] (int i) { 51 | if (array[i] != (1.0f * i)) { 52 | std::cout << "ERROR!" << std::endl; 53 | } 54 | }); 55 | 56 | array.free(); 57 | } 58 | -------------------------------------------------------------------------------- /examples/ex1.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "chai/ManagedArray.hpp" 8 | #include "chai/util/forall.hpp" 9 | 10 | int main(int CHAI_UNUSED_ARG(argc), char** CHAI_UNUSED_ARG(argv)) 11 | { 12 | /* 13 | * Allocate an array. 14 | */ 15 | chai::ManagedArray array(50); 16 | 17 | /* 18 | * Fill data on the device 19 | */ 20 | forall(gpu(), 0, 50, [=] __device__(int i) { array[i] = i * 2.0f; }); 21 | 22 | /* 23 | * Print the array on the host, data is automatically copied back. 24 | */ 25 | std::cout << "array = ["; 26 | forall(sequential(), 0, 10, [=](int i) { std::cout << " " << array[i]; }); 27 | std::cout << " ]" << std::endl; 28 | } 29 | -------------------------------------------------------------------------------- /examples/example.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "../src/util/forall.hpp" 8 | #include "chai/ManagedArray.hpp" 9 | 10 | #include 11 | 12 | int main(int CHAI_UNUSED_ARG(argc), char** CHAI_UNUSED_ARG(argv)) 13 | { 14 | 15 | std::cout << "Creating new arrays..." << std::endl; 16 | /* 17 | * Allocate two arrays with 10 elements of type float. 18 | */ 19 | chai::ManagedArray v1(10); 20 | chai::ManagedArray v2(10); 21 | 22 | /* 23 | * Allocate an array on the device only 24 | */ 25 | chai::ManagedArray device_array(10, chai::GPU); 26 | 27 | std::cout << "Arrays created." << std::endl; 28 | 29 | std::cout << "Setting v1 on host." << std::endl; 30 | forall(sequential(), 0, 10, [=](int i) { 31 | v1[i] = static_cast(i * 1.0f); 32 | }); 33 | 34 | std::cout << "v1 = ["; 35 | forall(sequential(), 0, 10, [=](int i) { std::cout << " " << v1[i]; }); 36 | std::cout << " ]" << std::endl; 37 | 38 | std::cout << "Setting v2 and device_array on device." << std::endl; 39 | forall(gpu(), 0, 10, [=] __device__(int i) { 40 | v2[i] = v1[i] * 2.0f; 41 | device_array[i] = i; 42 | }); 43 | 44 | std::cout << "v2 = ["; 45 | forall(sequential(), 0, 10, [=](int i) { std::cout << " " << v2[i]; }); 46 | std::cout << " ]" << std::endl; 47 | 48 | std::cout << "Doubling v2 on device." << std::endl; 49 | forall(gpu(), 0, 10, [=] __device__(int i) { v2[i] *= 2.0f; }); 50 | 51 | std::cout << "Extracting pointer from v2." << std::endl; 52 | float* raw_v2 = v2.data(); 53 | 54 | std::cout << "raw_v2 = ["; 55 | for (int i = 0; i < 10; i++) { 56 | std::cout << " " << raw_v2[i]; 57 | } 58 | std::cout << " ]" << std::endl; 59 | 60 | std::cout << "Extracting pointer from device_array." << std::endl; 61 | int* raw_device_array = device_array.data(); 62 | std::cout << "device_array = ["; 63 | for (int i = 0; i < 10; i++) { 64 | std::cout << " " << device_array[i]; 65 | } 66 | std::cout << " ]" << std::endl; 67 | 68 | v1.free(); 69 | v2.free(); 70 | device_array.free(); 71 | } 72 | -------------------------------------------------------------------------------- /examples/managed_ptr_example.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "chai/managed_ptr.hpp" 8 | #include "../src/util/forall.hpp" 9 | #include 10 | 11 | class TestBase { 12 | public: 13 | CHAI_HOST_DEVICE TestBase() {} 14 | CHAI_HOST_DEVICE virtual ~TestBase() {} 15 | CHAI_HOST_DEVICE virtual int getValue() const = 0; 16 | }; 17 | 18 | class TestDerived : public TestBase { 19 | public: 20 | CHAI_HOST_DEVICE TestDerived(const int value) : TestBase(), m_value(value) {} 21 | CHAI_HOST_DEVICE virtual ~TestDerived() {} 22 | CHAI_HOST_DEVICE virtual int getValue() const { return m_value; } 23 | 24 | private: 25 | int m_value; 26 | }; 27 | 28 | int main(int CHAI_UNUSED_ARG(argc), char** CHAI_UNUSED_ARG(argv)) 29 | { 30 | // Create an object on the host, and if either CUDA or HIP is enabled, 31 | // on the device as well 32 | chai::managed_ptr derived = chai::make_managed(42); 33 | 34 | // chai::managed_ptr can be accessed on the host 35 | forall(sequential(), 0, 1, [=] CHAI_HOST (int) { 36 | printf("Result of virtual function call on host: %d\n", derived->getValue()); 37 | }); 38 | 39 | #if defined(CHAI_GPUCC) 40 | // chai::managed_ptr can be accessed on the device 41 | forall(gpu(), 0, 1, [=] CHAI_DEVICE (int) { 42 | printf("Result of virtual function call on device: %d\n", derived->getValue()); 43 | }); 44 | #endif 45 | 46 | // Free the object on the host, and if either CUDA or HIP is enabled, 47 | // on the device as well 48 | derived.free(); 49 | 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /examples/pinned.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "../src/util/forall.hpp" 8 | #include "chai/ManagedArray.hpp" 9 | 10 | #include 11 | 12 | int main(int CHAI_UNUSED_ARG(argc), char** CHAI_UNUSED_ARG(argv)) 13 | { 14 | std::cout << "Creating a pinned array..." << std::endl; 15 | 16 | chai::ManagedArray array(10, chai::PINNED); 17 | 18 | std::cout << "Setting array on host." << std::endl; 19 | std::cout << "array = ["; 20 | forall(sequential(), 0, 10, [=](int i) { 21 | array[i] = static_cast(i * 1.0f); 22 | std::cout << " " << array[i]; 23 | }); 24 | std::cout << " ]" << std::endl; 25 | 26 | 27 | std::cout << "Doubling on device." << std::endl; 28 | forall(gpu_async(), 0, 10, [=] __device__(int i) { array[i] *= 2.0f; }); 29 | 30 | std::cout << "array = ["; 31 | forall(sequential(), 0, 10, [=](int i) { 32 | std::cout << " " << array[i]; 33 | }); 34 | std::cout << " ]" << std::endl; 35 | 36 | array.free(); 37 | 38 | chai::ManagedArray array_one(4096, chai::PINNED); 39 | chai::ManagedArray array_two(4096, chai::PINNED); 40 | chai::ManagedArray array_three(4096, chai::PINNED); 41 | chai::ManagedArray array_four(4096, chai::PINNED); 42 | chai::ManagedArray array_five(4096, chai::PINNED); 43 | 44 | std::cout << "Setting arrays on host." << std::endl; 45 | forall(sequential(), 0, 4096, [=](int i) { 46 | array_one[i] = static_cast(i * 1.0f); 47 | array_two[i] = static_cast(i * 2.0f); 48 | array_three[i] = static_cast(i * 3.0f); 49 | array_four[i] = static_cast(i * 4.0f); 50 | array_five[i] = static_cast(i * 5.0f); 51 | }); 52 | 53 | forall(sequential(), 0, 3, [=](int i) { 54 | std::cout << array_one[i] << " "; 55 | std::cout << array_two[i] << " "; 56 | std::cout << array_three[i] << " "; 57 | std::cout << array_four[i] << " "; 58 | std::cout << array_five[i] << " "; 59 | }); 60 | std::cout << std::endl; 61 | 62 | std::cout << "Doubling on device." << std::endl; 63 | forall(gpu_async(), 0, 4096, [=] __device__(int i) { 64 | array_one[i] *= 2.0f; 65 | array_two[i] *= 2.0f; 66 | array_three[i] *= 2.0f; 67 | array_four[i] *= 2.0f; 68 | array_five[i] *= 2.0f; 69 | }); 70 | 71 | forall(sequential(), 0, 3, [=](int i) { 72 | std::cout << array_one[i] << " "; 73 | std::cout << array_two[i] << " "; 74 | std::cout << array_three[i] << " "; 75 | std::cout << array_four[i] << " "; 76 | std::cout << array_five[i] << " "; 77 | }); 78 | std::cout << std::endl; 79 | 80 | array_one.free(); 81 | array_two.free(); 82 | array_three.free(); 83 | array_four.free(); 84 | array_five.free(); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /host-configs/lc/blueos_3_ppc64le_ib_p9/nvcc_clang.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | 8 | # Set up software versions 9 | set(CLANG_VERSION "ibm-14.0.5" CACHE PATH "") 10 | set(CUDA_VERSION "11.8.0" CACHE PATH "") 11 | set(GCC_VERSION "11.2.1" CACHE PATH "") 12 | 13 | # Set up compilers 14 | set(COMPILER_BASE "/usr/tce/packages/clang/clang-${CLANG_VERSION}" CACHE PATH "") 15 | set(CMAKE_C_COMPILER "${COMPILER_BASE}/bin/clang" CACHE PATH "") 16 | set(CMAKE_CXX_COMPILER "${COMPILER_BASE}/bin/clang++" CACHE PATH "") 17 | 18 | # Set up compiler flags 19 | set(GCC_HOME "/usr/tce/packages/gcc/gcc-${GCC_VERSION}" CACHE PATH "") 20 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 21 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 22 | 23 | # Prevent the wrong libraries from being linked in 24 | set(BLT_CMAKE_IMPLICIT_LINK_DIRECTORIES_EXCLUDE "/usr/tce/packages/gcc/gcc-4.9.3/lib64/gcc/powerpc64le-unknown-linux-gnu/4.9.3;/usr/tce/packages/gcc/gcc-4.9.3/lib64" CACHE STRING "") 25 | 26 | # Set up CUDA 27 | set(ENABLE_CUDA ON CACHE BOOL "Enable CUDA") 28 | set(CUDA_TOOLKIT_ROOT_DIR "/usr/tce/packages/cuda/cuda-${CUDA_VERSION}" CACHE PATH "Path to CUDA") 29 | set(CMAKE_CUDA_COMPILER "${CUDA_TOOLKIT_ROOT_DIR}/bin/nvcc" CACHE PATH "") 30 | set(CMAKE_CUDA_HOST_COMPILER "${CMAKE_CXX_COMPILER}" CACHE PATH "") 31 | set(CMAKE_CUDA_ARCHITECTURES "70" CACHE STRING "") 32 | set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=--gcc-toolchain=${GCC_HOME}" CACHE STRING "") 33 | -------------------------------------------------------------------------------- /host-configs/lc/toss_4_x86_64_ib/clang.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | 8 | # Set up software versions 9 | set(CLANG_VERSION "14.0.6" CACHE PATH "") 10 | set(GCC_VERSION "12.1.1" CACHE PATH "") 11 | 12 | # Set up compilers 13 | set(COMPILER_BASE "/usr/tce/packages/clang/clang-${CLANG_VERSION}-magic" CACHE PATH "") 14 | set(CMAKE_C_COMPILER "${COMPILER_BASE}/bin/clang" CACHE PATH "") 15 | set(CMAKE_CXX_COMPILER "${COMPILER_BASE}/bin/clang++" CACHE PATH "") 16 | 17 | # Set up compiler flags 18 | set(GCC_HOME "/usr/tce/packages/gcc/gcc-${GCC_VERSION}-magic" CACHE PATH "") 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 21 | -------------------------------------------------------------------------------- /host-configs/lc/toss_4_x86_64_ib/intel.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | 8 | # Set up software versions 9 | set(INTEL_VERSION "2022.1.0" CACHE PATH "") 10 | set(GCC_VERSION "12.1.1" CACHE PATH "") 11 | 12 | # Set up compilers 13 | set(COMPILER_BASE "/usr/tce/packages/intel/intel-${INTEL_VERSION}-magic" CACHE PATH "") 14 | set(CMAKE_C_COMPILER "${COMPILER_BASE}/bin/icx" CACHE PATH "") 15 | set(CMAKE_CXX_COMPILER "${COMPILER_BASE}/bin/icpx" CACHE PATH "") 16 | 17 | # Set up compiler flags 18 | set(GCC_HOME "/usr/tce/packages/gcc/gcc-${GCC_VERSION}-magic" CACHE PATH "") 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 21 | -------------------------------------------------------------------------------- /host-configs/lc/toss_4_x86_64_ib_cray/amdclang-xnack.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | 8 | # Set up software versions 9 | set(ROCM_VERSION "6.2.0" CACHE PATH "") 10 | set(GCC_VERSION "12.2.1" CACHE PATH "") 11 | 12 | # Set up compilers 13 | set(COMPILER_BASE "/usr/tce/packages/rocmcc/rocmcc-${ROCM_VERSION}-magic" CACHE PATH "") 14 | set(CMAKE_C_COMPILER "${COMPILER_BASE}/bin/amdclang" CACHE PATH "") 15 | set(CMAKE_CXX_COMPILER "${COMPILER_BASE}/bin/amdclang++" CACHE PATH "") 16 | 17 | # Set up compiler flags 18 | set(GCC_HOME "/usr/tce/packages/gcc/gcc-${GCC_VERSION}" CACHE PATH "") 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 21 | 22 | # Set up HIP 23 | set(ENABLE_HIP ON CACHE BOOL "") 24 | set(ROCM_PATH "/usr/tce/packages/rocmcc/rocmcc-${ROCM_VERSION}-magic" CACHE PATH "") 25 | set(CMAKE_HIP_ARCHITECTURES "gfx942:xnack+" CACHE STRING "") 26 | set(AMDGPU_TARGETS "${CMAKE_HIP_ARCHITECTURES}" CACHE STRING "") 27 | -------------------------------------------------------------------------------- /host-configs/lc/toss_4_x86_64_ib_cray/amdclang.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | 8 | # Set up software versions 9 | set(ROCM_VERSION "6.2.0" CACHE PATH "") 10 | set(GCC_VERSION "12.2.1" CACHE PATH "") 11 | 12 | # Set up compilers 13 | set(COMPILER_BASE "/usr/tce/packages/rocmcc/rocmcc-${ROCM_VERSION}-magic" CACHE PATH "") 14 | set(CMAKE_C_COMPILER "${COMPILER_BASE}/bin/amdclang" CACHE PATH "") 15 | set(CMAKE_CXX_COMPILER "${COMPILER_BASE}/bin/amdclang++" CACHE PATH "") 16 | 17 | # Set up compiler flags 18 | set(GCC_HOME "/usr/tce/packages/gcc/gcc-${GCC_VERSION}" CACHE PATH "") 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${GCC_HOME}" CACHE STRING "") 21 | 22 | # Set up HIP 23 | set(ENABLE_HIP ON CACHE BOOL "") 24 | set(ROCM_PATH "/usr/tce/packages/rocmcc/rocmcc-${ROCM_VERSION}-magic" CACHE PATH "") 25 | set(CMAKE_HIP_ARCHITECTURES "gfx942" CACHE STRING "") 26 | set(AMDGPU_TARGETS "${CMAKE_HIP_ARCHITECTURES}" CACHE STRING "") 27 | -------------------------------------------------------------------------------- /reproducers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | set (chai_reproducer_depends chai) 8 | 9 | if (CHAI_ENABLE_CUDA) 10 | list(APPEND chai_reproducer_depends cuda) 11 | endif () 12 | 13 | if (CHAI_ENABLE_HIP) 14 | list(APPEND chai_reproducer_depends blt::hip) 15 | endif () 16 | 17 | if (CHAI_ENABLE_MANAGED_PTR AND (CHAI_ENABLE_HIP OR CHAI_ENABLE_CUDA)) 18 | # This crashes with HIP but not with CUDA 19 | blt_add_executable( 20 | NAME managed_ptr_multiple_inheritance_reproducer.exe 21 | SOURCES managed_ptr_multiple_inheritance_reproducer.cpp 22 | DEPENDS_ON ${chai_reproducer_depends}) 23 | endif () 24 | 25 | if (CHAI_ENABLE_MANAGED_PTR AND CHAI_ENABLE_HIP) 26 | blt_add_executable( 27 | NAME virtual_function_simple_reproducer.exe 28 | SOURCES virtual_function_simple_reproducer.cpp 29 | DEPENDS_ON ${chai_reproducer_depends}) 30 | 31 | blt_add_executable( 32 | NAME virtual_function_complex_reproducer.exe 33 | SOURCES virtual_function_complex_reproducer.cpp 34 | DEPENDS_ON ${chai_reproducer_depends}) 35 | 36 | blt_add_executable( 37 | NAME managed_ptr_reproducer.exe 38 | SOURCES managed_ptr_reproducer.cpp 39 | DEPENDS_ON ${chai_reproducer_depends}) 40 | endif () 41 | 42 | -------------------------------------------------------------------------------- /reproducers/managed_ptr_multiple_inheritance_reproducer.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // To reproduce crash on with a ROCM compiler: 9 | // % mkdir build_rocm 10 | // % cd build_rocm 11 | // % cmake -DCHAI_ENABLE_REPRODUCERS=1 -C ../host-configs/lc/toss_4_x86_64_ib_cray/amdclang.cmake .. 12 | // % flux alloc -N 1 -n 1 -g1 make -j 40 13 | // % flux alloc -N 1 -n 1 -g1 ./bin/managed_ptr_multiple_inheritance_reproducer.exe 14 | // 15 | // - Note that the "this" pointer in YofXfromRTTable1D::RootFromBaseX differs from the 16 | // "this" pointer in other YofXfromRTTable1D methods. The crash occurs because m_table is null 17 | // and is dereferenced. 18 | // - Interestingly , the crash goes away if GetNumStrings() is removed 19 | // 20 | // The NVCC case does not crash and has consistent pointer addresses in YofXfromRTTable1D. 21 | // This can be reproduced with: 22 | // % mkdir build_cuda 23 | // % cd build_cuda 24 | // % cmake -DCHAI_ENABLE_REPRODUCERS=1 -C ../host-configs/lc/blueos_3_ppc64le_ib_p9/nvcc_clang.cmake .. 25 | // % lalloc 1 make -j 40 26 | // % lalloc 1 ./bin/managed_ptr_multiple_inheritance_reproducer.exe 27 | // 28 | 29 | #include "chai/config.hpp" 30 | #include "chai/managed_ptr.hpp" 31 | #include "chai/ArrayManager.hpp" 32 | #include "chai/ManagedArray.hpp" 33 | #include 34 | #include 35 | #include 36 | 37 | class Table { 38 | public: 39 | CHAI_HOST_DEVICE Table() { 40 | #ifdef CHAI_DEVICE_COMPILE 41 | printf("Table::Table POINTER %p\n", this) ; 42 | #endif 43 | } 44 | 45 | CHAI_HOST_DEVICE virtual ~Table() {} 46 | 47 | class Data { 48 | public: 49 | CHAI_HOST_DEVICE Data() { 50 | #ifdef CHAI_DEVICE_COMPILE 51 | printf("Table::Data::Data POINTER %p\n", this) ; 52 | #endif 53 | } 54 | 55 | CHAI_HOST_DEVICE virtual ~Data() {} 56 | 57 | private: 58 | } ; 59 | 60 | class Derived { 61 | public: 62 | CHAI_HOST_DEVICE Derived() { 63 | #ifdef CHAI_DEVICE_COMPILE 64 | printf("Table::Derived::Derived POINTER %p\n", this) ; 65 | #endif 66 | } 67 | 68 | CHAI_HOST_DEVICE virtual ~Derived() {} 69 | 70 | /// Removing this makes the bug go away!!! 71 | virtual int GetNumStrings() const = 0 ; 72 | } ; 73 | 74 | class Compute { 75 | public: 76 | CHAI_HOST_DEVICE Compute() { 77 | #ifdef CHAI_DEVICE_COMPILE 78 | printf("Table::Compute::Compute POINTER %p\n", this) ; 79 | #endif 80 | } 81 | 82 | CHAI_HOST_DEVICE virtual ~Compute() {} 83 | 84 | protected: 85 | 86 | CHAI_HOST_DEVICE double BaseXFromNewX() const { 87 | #ifdef CHAI_DEVICE_COMPILE 88 | printf("Table::Compute::BaseXFromNewX %p\n", this) ; 89 | #endif 90 | RootFromBaseX() ; 91 | return 0.0 ; 92 | } 93 | 94 | CHAI_HOST_DEVICE virtual double RootFromBaseX() const = 0; 95 | 96 | private: 97 | Compute(const Compute &other); 98 | Compute &operator=(const Compute &other); 99 | } ; 100 | private: 101 | 102 | Table(const Table &other); 103 | 104 | Table& operator =(const Table&); 105 | }; 106 | 107 | class SimpleTable : public Table { 108 | public: 109 | CHAI_HOST_DEVICE SimpleTable() : Table() { 110 | #ifdef CHAI_DEVICE_COMPILE 111 | printf("SimpleTable::SimpleTable POINTER %p\n", this) ; 112 | #endif 113 | } 114 | 115 | 116 | CHAI_HOST_DEVICE virtual ~SimpleTable() {} 117 | 118 | private: 119 | SimpleTable(const SimpleTable& other); 120 | 121 | SimpleTable& operator =(const SimpleTable&); 122 | }; 123 | 124 | class Table1D : public SimpleTable { 125 | public: 126 | CHAI_HOST_DEVICE Table1D() : SimpleTable() { 127 | #ifdef CHAI_DEVICE_COMPILE 128 | printf("Table1D::Table1D POINTER %p\n", this) ; 129 | #endif 130 | } 131 | 132 | CHAI_HOST_DEVICE virtual ~Table1D() {} 133 | 134 | CHAI_HOST_DEVICE virtual double Evaluate() const = 0 ; 135 | 136 | protected: 137 | CHAI_HOST_DEVICE Table1D(const Table1D &other) = delete; 138 | 139 | CHAI_HOST_DEVICE Table1D& operator=(const Table1D &other) = delete; 140 | } ; 141 | 142 | class DataTable1D : public Table1D, public Table::Data { 143 | public: 144 | CHAI_HOST_DEVICE DataTable1D() : Table1D(), Table::Data() {} 145 | 146 | CHAI_HOST_DEVICE virtual ~DataTable1D() {} 147 | 148 | CHAI_HOST_DEVICE virtual double Evaluate() const override { 149 | return innerEvaluate() ; 150 | } 151 | 152 | protected: 153 | CHAI_HOST_DEVICE virtual double innerEvaluate() const = 0 ; 154 | } ; 155 | 156 | class LinearTable1D : public DataTable1D { 157 | public: 158 | CHAI_HOST_DEVICE LinearTable1D() : DataTable1D() {} 159 | 160 | CHAI_HOST_DEVICE virtual ~LinearTable1D() {} 161 | 162 | CHAI_HOST_DEVICE virtual double innerEvaluate() const override { 163 | return 0.0 ; 164 | } 165 | 166 | private: 167 | CHAI_HOST_DEVICE LinearTable1D(const LinearTable1D &other) = delete; 168 | CHAI_HOST_DEVICE LinearTable1D &operator=(const LinearTable1D &other) = delete; 169 | } ; 170 | 171 | 172 | class DerivedTable1D : public Table1D, public Table::Data, public Table::Derived { 173 | public: 174 | CHAI_HOST_DEVICE DerivedTable1D() : Table1D(), Table::Data(), Table::Derived() { 175 | #ifdef CHAI_DEVICE_COMPILE 176 | printf("DerivedTable1D::DerivedTable1D POINTER %p\n", this) ; 177 | #endif 178 | } 179 | 180 | CHAI_HOST_DEVICE virtual ~DerivedTable1D() {} 181 | 182 | CHAI_HOST_DEVICE virtual double Evaluate() const override { 183 | #ifdef CHAI_DEVICE_COMPILE 184 | printf("DerivedTable1D::Evaluate POINTER %p\n", this) ; 185 | #endif 186 | return innerEvaluate() ; 187 | } 188 | 189 | virtual int GetNumStrings() const override = 0; 190 | 191 | protected: 192 | 193 | CHAI_HOST_DEVICE virtual double innerEvaluate() const = 0 ; 194 | 195 | private: 196 | CHAI_HOST_DEVICE DerivedTable1D(const DerivedTable1D &other) = delete; 197 | CHAI_HOST_DEVICE DerivedTable1D &operator=(const DerivedTable1D &other) = delete; 198 | } ; 199 | 200 | class StitchTable1D : public DerivedTable1D { 201 | public: 202 | CHAI_HOST_DEVICE StitchTable1D(int nt, chai::managed_ptr* tabs) : DerivedTable1D(), m_nTables(nt), m_tables(new const Table1D *[nt]) { 203 | for (int i = 0 ; i < nt ; ++i) { 204 | m_tables[i] = tabs[i].get() ; 205 | #ifdef CHAI_DEVICE_COMPILE 206 | printf("StitchTable1D::StitchTable1D POINTER %p i %d m_tables[i] %p\n", this, i, m_tables[i]) ; 207 | #endif 208 | } 209 | } 210 | 211 | CHAI_HOST_DEVICE virtual ~StitchTable1D() { 212 | if (m_nTables > 0) { 213 | delete [] m_tables ; 214 | } 215 | } 216 | 217 | inline virtual int GetNumStrings() const override { return m_nTables; } 218 | 219 | private: 220 | CHAI_HOST_DEVICE double innerEvaluate() const override { 221 | for (int i = 0 ; i < m_nTables ; ++i) { 222 | #ifdef CHAI_DEVICE_COMPILE 223 | printf("StitchTable1D::innerEvaluate POINTER %p i %d m_tables[i] %p\n", this, i, m_tables[i]) ; 224 | #endif 225 | m_tables[i]->Evaluate() ; 226 | } 227 | return 0.0 ; 228 | } 229 | 230 | CHAI_HOST_DEVICE StitchTable1D() = delete; 231 | CHAI_HOST_DEVICE StitchTable1D(const StitchTable1D &other) = delete; 232 | CHAI_HOST_DEVICE StitchTable1D &operator=(const StitchTable1D &other) = delete; 233 | 234 | int m_nTables ; 235 | const Table1D ** m_tables = nullptr; 236 | } ; 237 | 238 | class ComputedTable1D : public DerivedTable1D, public Table::Compute { 239 | public: 240 | CHAI_HOST_DEVICE ComputedTable1D(const Table1D * f) : DerivedTable1D(), Table::Compute(), m_table(f) 241 | { 242 | #ifdef CHAI_DEVICE_COMPILE 243 | printf("ComputedTable1D::ComputedTable1D POINTER %p m_table %p\n", this, m_table) ; 244 | #endif 245 | } 246 | 247 | CHAI_HOST_DEVICE virtual ~ComputedTable1D() {} 248 | 249 | protected: 250 | const Table1D *m_table; 251 | 252 | private: 253 | CHAI_HOST_DEVICE ComputedTable1D() = delete; 254 | CHAI_HOST_DEVICE ComputedTable1D(const ComputedTable1D &other) = delete; 255 | CHAI_HOST_DEVICE ComputedTable1D& operator=(const ComputedTable1D &other) = delete; 256 | } ; 257 | 258 | class YofXfromRTTable1D : public ComputedTable1D { 259 | public: 260 | CHAI_HOST_DEVICE YofXfromRTTable1D(Table1D const * f) : ComputedTable1D(f) { 261 | #ifdef CHAI_DEVICE_COMPILE 262 | printf("YofXfromRTTable1D::YofXfromRTTable1D POINTER %p m_table %p <<< CHECK THESE POINTERS\n", this, m_table) ; 263 | #endif 264 | m_table->Evaluate() ; 265 | } 266 | 267 | CHAI_HOST_DEVICE virtual ~YofXfromRTTable1D() {} 268 | 269 | inline int virtual GetNumStrings() const override { return 1; } 270 | 271 | private: 272 | CHAI_HOST_DEVICE virtual double innerEvaluate() const override { 273 | #ifdef CHAI_DEVICE_COMPILE 274 | printf("YofXfromRTTable1D::innerEvaluate POINTER %p m_table %p <<< CHECK THESE POINTERS\n", this, m_table) ; 275 | #endif 276 | BaseXFromNewX() ; 277 | return 0.0 ; 278 | } 279 | 280 | CHAI_HOST_DEVICE virtual double RootFromBaseX() const override { 281 | #ifdef CHAI_DEVICE_COMPILE 282 | printf("YofXfromRTTable1D::RootFromBaseX POINTER %p m_table %p <<< CHECK THESE POINTERS\n", this, m_table) ; 283 | #endif 284 | return m_table->Evaluate() ; 285 | } 286 | 287 | CHAI_HOST_DEVICE YofXfromRTTable1D() = delete; 288 | CHAI_HOST_DEVICE YofXfromRTTable1D(const YofXfromRTTable1D &other) = delete; 289 | CHAI_HOST_DEVICE YofXfromRTTable1D &operator=(const YofXfromRTTable1D &other) = delete; 290 | } ; 291 | 292 | class RofTfromXYTable1D : public ComputedTable1D { 293 | public: 294 | CHAI_HOST_DEVICE RofTfromXYTable1D(Table1D const * f) : ComputedTable1D(f) { 295 | #ifdef CHAI_DEVICE_COMPILE 296 | printf("RofTfromXY::RofTfromXYTable1D POINTER %p m_table %p\n", this, m_table) ; 297 | #endif 298 | 299 | m_table->Evaluate() ; 300 | } 301 | 302 | CHAI_HOST_DEVICE virtual ~RofTfromXYTable1D() {} 303 | 304 | inline int virtual GetNumStrings() const override { return 1; } 305 | 306 | private: 307 | CHAI_HOST_DEVICE virtual double innerEvaluate() const override { 308 | BaseXFromNewX() ; 309 | return 0.0 ; 310 | } 311 | 312 | CHAI_HOST_DEVICE virtual double RootFromBaseX() const override { 313 | return m_table->Evaluate() ; 314 | } 315 | 316 | CHAI_HOST_DEVICE RofTfromXYTable1D() = delete; 317 | CHAI_HOST_DEVICE RofTfromXYTable1D(const RofTfromXYTable1D &other) = delete; 318 | CHAI_HOST_DEVICE RofTfromXYTable1D &operator=(const RofTfromXYTable1D &other) = delete; 319 | } ; 320 | 321 | int main(int, char**) { 322 | chai::managed_ptr tabArray[6] ; 323 | 324 | tabArray[0] = chai::make_managed() ; 325 | tabArray[1] = chai::make_managed(chai::unpack(tabArray[0])) ; 326 | tabArray[2] = chai::make_managed() ; 327 | tabArray[3] = chai::make_managed() ; 328 | 329 | chai::ManagedArray > host_device_temp0(2) ; 330 | chai::managed_ptr *host_temp0 = host_device_temp0.data() ; 331 | host_temp0[0] = tabArray[1] ; 332 | host_temp0[1] = tabArray[2] ; 333 | 334 | tabArray[4] = chai::make_managed(2, chai::unpack(host_device_temp0)) ; 335 | 336 | chai::ManagedArray > host_device_temp1(2) ; 337 | chai::managed_ptr *host_temp1 = host_device_temp1.data() ; 338 | host_temp1[0] = tabArray[3] ; 339 | host_temp1[1] = tabArray[4] ; 340 | 341 | tabArray[5] = chai::make_managed(2, chai::unpack(host_device_temp1)) ; 342 | 343 | chai::make_managed(chai::unpack(tabArray[5])) ; 344 | 345 | printf("SUCCESS\n") ; 346 | 347 | host_device_temp0.free() ; 348 | host_device_temp1.free() ; 349 | 350 | return 0; 351 | } 352 | 353 | -------------------------------------------------------------------------------- /reproducers/managed_ptr_reproducer.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "chai/managed_ptr.hpp" 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class TestBase { 14 | public: 15 | __host__ __device__ TestBase() {} 16 | __host__ __device__ virtual ~TestBase() {} 17 | __host__ __device__ virtual int getValue() const = 0; 18 | }; 19 | 20 | class TestDerived : public TestBase { 21 | public: 22 | __host__ __device__ TestDerived(const int value) : TestBase(), m_value(value) {} 23 | __host__ __device__ virtual ~TestDerived() {} 24 | __host__ __device__ virtual int getValue() const { return m_value; } 25 | 26 | private: 27 | int m_value; 28 | }; 29 | 30 | __global__ void callDeviceVirtualFunction(int* d_result, 31 | chai::managed_ptr derived) { 32 | *d_result = derived->getValue(); 33 | } 34 | 35 | int main(int, char**) { 36 | chai::managed_ptr derived = chai::make_managed(42); 37 | 38 | int* d_result; 39 | hipMalloc(&d_result, sizeof(int)); 40 | 41 | hipLaunchKernelGGL(callDeviceVirtualFunction, 1, 1, 0, 0, d_result, derived); 42 | 43 | int* h_result = (int*) malloc(sizeof(int)); 44 | hipMemcpyDtoH(h_result, d_result, sizeof(int)); 45 | 46 | printf("Result: %d\n", *h_result); 47 | 48 | free(h_result); 49 | hipFree(d_result); 50 | derived.free(); 51 | 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /reproducers/virtual_function_complex_reproducer.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "chai/managed_ptr.hpp" 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class TestBase { 14 | public: 15 | __host__ __device__ TestBase() {} 16 | __host__ __device__ virtual ~TestBase() {} 17 | __host__ __device__ virtual int getValue() const = 0; 18 | }; 19 | 20 | class TestDerived : public TestBase { 21 | public: 22 | __host__ __device__ TestDerived(const int value) : TestBase(), m_value(value) {} 23 | __host__ __device__ virtual ~TestDerived() {} 24 | __host__ __device__ virtual int getValue() const { return m_value; } 25 | 26 | private: 27 | int m_value; 28 | }; 29 | 30 | __global__ void createOnDevice(TestDerived** ptr, int val) { 31 | *ptr = new TestDerived(val); 32 | } 33 | 34 | __global__ void destroyOnDevice(TestBase* ptr) { 35 | delete ptr; 36 | } 37 | 38 | __global__ void callDeviceVirtualFunction(int* d_result, TestBase* derived) { 39 | *d_result = derived->getValue(); 40 | } 41 | 42 | int main(int, char**) { 43 | // Allocate space on the GPU to hold the pointer to the new object 44 | TestDerived** gpuBuffer; 45 | hipMalloc((void**)(&gpuBuffer), sizeof(TestDerived*)); 46 | 47 | // New the object on the device 48 | hipLaunchKernelGGL(createOnDevice, 1, 1, 0, 0, gpuBuffer, 42); 49 | 50 | // Allocate space on the CPU for the GPU pointer and copy the pointer to the CPU 51 | TestDerived** cpuBuffer = (TestDerived**) malloc(sizeof(TestDerived*)); 52 | hipMemcpyDtoH(cpuBuffer, gpuBuffer, sizeof(TestDerived*)); 53 | 54 | // Extract the pointer to the object on the GPU 55 | TestBase* derived = *cpuBuffer; 56 | 57 | // Free the host and device buffers 58 | free(cpuBuffer); 59 | hipFree(gpuBuffer); 60 | 61 | // Allocate space to hold the result of calling a virtual function on the device 62 | int* d_result; 63 | hipMalloc(&d_result, sizeof(int)); 64 | 65 | // Call a virtual function on the device 66 | hipLaunchKernelGGL(callDeviceVirtualFunction, 1, 1, 0, 0, d_result, derived); 67 | 68 | // Copy the result to the CPU 69 | int* h_result = (int*) malloc(sizeof(int)); 70 | hipMemcpyDtoH(h_result, d_result, sizeof(int)); 71 | 72 | // Print the result 73 | printf("Result: %d\n", *h_result); 74 | 75 | // Free memory 76 | free(h_result); 77 | hipFree(d_result); 78 | 79 | // Delete the object on the device 80 | hipLaunchKernelGGL(destroyOnDevice, 1, 1, 0, 0, derived); 81 | 82 | return 0; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /reproducers/virtual_function_simple_reproducer.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "chai/managed_ptr.hpp" 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class TestBase { 14 | public: 15 | __host__ __device__ TestBase() {} 16 | __host__ __device__ virtual ~TestBase() {} 17 | __host__ __device__ virtual int getValue() const = 0; 18 | }; 19 | 20 | class TestDerived : public TestBase { 21 | public: 22 | __host__ __device__ TestDerived(const int value) : TestBase(), m_value(value) {} 23 | __host__ __device__ virtual ~TestDerived() {} 24 | __host__ __device__ virtual int getValue() const { return m_value; } 25 | 26 | private: 27 | int m_value; 28 | }; 29 | 30 | __global__ void callVirtualFunction() { 31 | TestBase* derived = new TestDerived(42); 32 | int result = derived->getValue(); 33 | (void) result; 34 | return; 35 | } 36 | 37 | int main(int, char**) { 38 | hipLaunchKernelGGL(callVirtualFunction, 1, 1, 0, 0); 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /scripts/apply-license-info.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | ############################################################################## 3 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 4 | # project contributors. See the CHAI LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: BSD-3-Clause 7 | ############################################################################## 8 | 9 | setopt extended_glob 10 | 11 | RED="\033[1;31m" 12 | GREEN="\033[1;32m" 13 | NOCOLOR="\033[0m" 14 | 15 | LIC_CMD=$(which lic) 16 | if [ ! $LIC_CMD ]; then 17 | echo "${RED} [!] This script requires the lic command." 18 | exit 255 19 | fi 20 | 21 | echo "Applying licenses to files" 22 | 23 | files_no_license=$(grep -L 'This file is part of Umpire.' \ 24 | benchmarks/**/*(^/) \ 25 | cmake/**/*(^/) \ 26 | docs/**/*~*rst(^/)\ 27 | examples/**/*(^/) \ 28 | scripts/**/*(^/) \ 29 | src/**/*~*tpl*(^/) \ 30 | tests/**/*(^/) \ 31 | CMakeLists.txt) 32 | 33 | echo $files_no_license | xargs $LIC_CMD -f scripts/license.txt 34 | 35 | echo "${GREEN} [Ok] License text applied. ${NOCOLOR}" 36 | -------------------------------------------------------------------------------- /scripts/check-license-info.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | ############################################################################## 3 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 4 | # project contributors. See the CHAI LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: (MIT) 7 | ############################################################################## 8 | 9 | # This is used for the ~*tpl* line to ignore files in bundled tpls 10 | setopt extended_glob 11 | 12 | autoload colors 13 | 14 | RED="\033[1;31m" 15 | GREEN="\033[1;32m" 16 | NOCOLOR="\033[0m" 17 | 18 | files_no_license=$(grep -rL "the CHAI LICENSE file" . \ 19 | --exclude-dir=.git \ 20 | --exclude-dir=blt \ 21 | --exclude-dir=umpire \ 22 | --exclude-dir=raja \ 23 | --exclude-dir=radiuss-spack-configs \ 24 | --exclude-dir=uberenv) 25 | 26 | if [ $files_no_license ]; then 27 | print "${RED} [!] Some files are missing license text: ${NOCOLOR}" 28 | echo "${files_no_license}" 29 | exit 255 30 | else 31 | print "${GREEN} [Ok] All files have required license info.${NOCOLOR}" 32 | exit 0 33 | fi 34 | -------------------------------------------------------------------------------- /scripts/format-source.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ############################################################################## 3 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 4 | # project contributors. See the CHAI LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: BSD-3-Clause 7 | ############################################################################## 8 | 9 | find . -type f -iname '*.hpp' -o -iname '*.cpp' | grep -v -e blt -e tpl | xargs clang-format -i 10 | -------------------------------------------------------------------------------- /scripts/gitlab/build_and_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Initialize modules for users not using bash as a default shell 4 | if test -e /usr/share/lmod/lmod/init/bash 5 | then 6 | . /usr/share/lmod/lmod/init/bash 7 | fi 8 | 9 | ############################################################################## 10 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 11 | # project contributors. See the CHAI LICENSE file for details. 12 | # 13 | # SPDX-License-Identifier: BSD-3-Clause 14 | ############################################################################## 15 | 16 | set -o errexit 17 | set -o nounset 18 | 19 | option=${1:-""} 20 | hostname="$(hostname)" 21 | truehostname=${hostname//[0-9]/} 22 | project_dir="$(pwd)" 23 | 24 | hostconfig=${HOST_CONFIG:-""} 25 | spec=${SPEC:-""} 26 | module_list=${MODULE_LIST:-""} 27 | job_unique_id=${CI_JOB_ID:-""} 28 | use_dev_shm=${USE_DEV_SHM:-true} 29 | spack_debug=${SPACK_DEBUG:-false} 30 | debug_mode=${DEBUG_MODE:-false} 31 | push_to_registry=${PUSH_TO_REGISTRY:-true} 32 | 33 | # REGISTRY_TOKEN allows you to provide your own personal access token to the CI 34 | # registry. Be sure to set the token with at least read access to the registry. 35 | registry_token=${REGISTRY_TOKEN:-""} 36 | ci_registry_image=${CI_REGISTRY_IMAGE:-"czregistry.llnl.gov:5050/radiuss/chai"} 37 | export ci_registry_user=${CI_REGISTRY_USER:-"${USER}"} 38 | export ci_registry_token=${CI_JOB_TOKEN:-"${registry_token}"} 39 | 40 | timed_message () 41 | { 42 | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 43 | echo "~ $(date --rfc-3339=seconds) ~ ${1}" 44 | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 45 | } 46 | 47 | raja_version=${UPDATE_RAJA:-""} 48 | umpire_version=${UPDATE_UMPIRE:-""} 49 | 50 | if [[ ${debug_mode} == true ]] 51 | then 52 | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 53 | echo "~~~~~ Debug mode:" 54 | echo "~~~~~ - Spack debug mode." 55 | echo "~~~~~ - Deactivated shared memory." 56 | echo "~~~~~ - Do not push to buildcache." 57 | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 58 | use_dev_shm=false 59 | spack_debug=true 60 | push_to_registry=false 61 | fi 62 | 63 | if [[ -n ${module_list} ]] 64 | then 65 | timed_message "Modules to load: ${module_list}" 66 | module load ${module_list} 67 | fi 68 | 69 | prefix="" 70 | 71 | if [[ -d /dev/shm && ${use_dev_shm} == true ]] 72 | then 73 | prefix="/dev/shm/${hostname}" 74 | if [[ -z ${job_unique_id} ]]; then 75 | job_unique_id=manual_job_$(date +%s) 76 | while [[ -d ${prefix}-${job_unique_id} ]] ; do 77 | sleep 1 78 | job_unique_id=manual_job_$(date +%s) 79 | done 80 | fi 81 | 82 | prefix="${prefix}-${job_unique_id}" 83 | else 84 | # We set the prefix in the parent directory so that spack dependencies are not installed inside the source tree. 85 | prefix="${project_dir}/../spack-and-build-root" 86 | fi 87 | 88 | echo "Creating directory ${prefix}" 89 | echo "project_dir: ${project_dir}" 90 | 91 | mkdir -p ${prefix} 92 | 93 | spack_cmd="${prefix}/spack/bin/spack" 94 | spack_env_path="${prefix}/spack_env" 95 | uberenv_cmd="./scripts/uberenv/uberenv.py" 96 | if [[ ${spack_debug} == true ]] 97 | then 98 | spack_cmd="${spack_cmd} --debug --stacktrace" 99 | uberenv_cmd="${uberenv_cmd} --spack-debug" 100 | fi 101 | 102 | # Dependencies 103 | if [[ "${option}" != "--build-only" && "${option}" != "--test-only" ]] 104 | then 105 | timed_message "Building dependencies" 106 | 107 | if [[ -z ${spec} ]] 108 | then 109 | echo "[Error]: SPEC is undefined, aborting..." 110 | exit 1 111 | fi 112 | 113 | extra_variants="" 114 | extra_deps="" 115 | 116 | if [[ -n ${raja_version} ]] 117 | then 118 | extra_variants="${extra_variants} +raja" 119 | extra_deps="${extra_deps} ^raja@${raja_version}" 120 | fi 121 | 122 | if [[ -n ${umpire_version} ]] 123 | then 124 | extra_deps="${extra_deps} ^umpire@${umpire_version}" 125 | fi 126 | 127 | [[ -n ${extra_variants} ]] && spec="${spec} ${extra_variants}" 128 | [[ -n ${extra_deps} ]] && spec="${spec} ${extra_deps}" 129 | 130 | prefix_opt="--prefix=${prefix}" 131 | 132 | # We force Spack to put all generated files (cache and configuration of 133 | # all sorts) in a unique location so that there can be no collision 134 | # with existing or concurrent Spack. 135 | spack_user_cache="${prefix}/spack-user-cache" 136 | export SPACK_DISABLE_LOCAL_CONFIG="" 137 | export SPACK_USER_CACHE_PATH="${spack_user_cache}" 138 | mkdir -p ${spack_user_cache} 139 | 140 | # generate cmake cache file with uberenv and radiuss spack package 141 | timed_message "Spack setup and environment" 142 | ${uberenv_cmd} --setup-and-env-only --spec="${spec}" ${prefix_opt} 143 | 144 | if [[ -n ${ci_registry_token} ]] 145 | then 146 | timed_message "GitLab registry as Spack Buildcache" 147 | ${spack_cmd} -D ${spack_env_path} mirror add --unsigned --oci-username-variable ci_registry_user --oci-password-variable ci_registry_token gitlab_ci oci://${ci_registry_image} 148 | fi 149 | 150 | timed_message "Spack build of dependencies" 151 | ${uberenv_cmd} --skip-setup-and-env --spec="${spec}" ${prefix_opt} 152 | 153 | if [[ -n ${ci_registry_token} && ${push_to_registry} == true ]] 154 | then 155 | timed_message "Push dependencies to buildcache" 156 | ${spack_cmd} -D ${spack_env_path} buildcache push --only dependencies gitlab_ci 157 | fi 158 | 159 | timed_message "Dependencies built" 160 | fi 161 | 162 | # Find cmake cache file (hostconfig) 163 | if [[ -z ${hostconfig} ]] 164 | then 165 | # If no host config file was provided, we assume it was generated. 166 | # This means we are looking of a unique one in project dir. 167 | hostconfigs=( $( ls "${project_dir}/"*.cmake ) ) 168 | if [[ ${#hostconfigs[@]} == 1 ]] 169 | then 170 | hostconfig_path=${hostconfigs[0]} 171 | elif [[ ${#hostconfigs[@]} == 0 ]] 172 | then 173 | echo "[Error]: No result for: ${project_dir}/*.cmake" 174 | echo "[Error]: Spack generated host-config not found." 175 | exit 1 176 | else 177 | echo "[Error]: More than one result for: ${project_dir}/*.cmake" 178 | echo "[Error]: ${hostconfigs[@]}" 179 | echo "[Error]: Please specify one with HOST_CONFIG variable" 180 | exit 1 181 | fi 182 | else 183 | # Using provided host-config file. 184 | hostconfig_path="${project_dir}/${hostconfig}" 185 | fi 186 | 187 | hostconfig=$(basename ${hostconfig_path}) 188 | echo "[Information]: Found hostconfig ${hostconfig_path}" 189 | 190 | # Build Directory 191 | # When using /dev/shm, we use prefix for both spack builds and source build, unless BUILD_ROOT was defined 192 | build_root=${BUILD_ROOT:-"${prefix}"} 193 | 194 | build_dir="${build_root}/build_${hostconfig//.cmake/}" 195 | install_dir="${build_root}/install_${hostconfig//.cmake/}" 196 | 197 | cmake_exe=`grep 'CMake executable' ${hostconfig_path} | cut -d ':' -f 2 | xargs` 198 | 199 | # Build 200 | if [[ "${option}" != "--deps-only" && "${option}" != "--test-only" ]] 201 | then 202 | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 203 | echo "~~~~~ Prefix: ${prefix}" 204 | echo "~~~~~ Host-config: ${hostconfig_path}" 205 | echo "~~~~~ Build Dir: ${build_dir}" 206 | echo "~~~~~ Project Dir: ${project_dir}" 207 | echo "~~~~~ Install Dir: ${install_dir}" 208 | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 209 | echo "" 210 | timed_message "Cleaning working directory" 211 | 212 | # Map CPU core allocations 213 | declare -A core_counts=(["lassen"]=40 ["ruby"]=28 ["poodle"]=28 ["corona"]=32 ["rzansel"]=48 ["tioga"]=32) 214 | 215 | # If building, then delete everything first 216 | # NOTE: 'cmake --build . -j core_counts' attempts to reduce individual build resources. 217 | # If core_counts does not contain hostname, then will default to '-j ', which should 218 | # use max cores. 219 | rm -rf ${build_dir} 2>/dev/null 220 | mkdir -p ${build_dir} && cd ${build_dir} 221 | 222 | timed_message "Building CHAI" 223 | # We set the MPI tests command to allow overlapping. 224 | # Shared allocation: Allows build_and_test.sh to run within a sub-allocation (see CI config). 225 | # Use /dev/shm: Prevent MPI tests from running on a node where the build dir doesn't exist. 226 | cmake_options="" 227 | if [[ "${truehostname}" == "ruby" || "${truehostname}" == "poodle" ]] 228 | then 229 | cmake_options="-DBLT_MPI_COMMAND_APPEND:STRING=--overlap" 230 | fi 231 | 232 | $cmake_exe \ 233 | -C ${hostconfig_path} \ 234 | ${cmake_options} \ 235 | -DCMAKE_INSTALL_PREFIX=${install_dir} \ 236 | ${project_dir} 237 | if ! $cmake_exe --build . -j ${core_counts[$truehostname]} 238 | then 239 | echo "[Error]: Compilation failed, building with verbose output..." 240 | timed_message "Re-building with --verbose" 241 | $cmake_exe --build . --verbose -j 1 242 | else 243 | timed_message "Installing" 244 | $cmake_exe --install . 245 | fi 246 | 247 | timed_message "CHAI built and installed" 248 | fi 249 | 250 | # Test 251 | if [[ "${option}" != "--build-only" ]] && grep -q -i "ENABLE_TESTS.*ON" ${hostconfig_path} 252 | then 253 | 254 | if [[ ! -d ${build_dir} ]] 255 | then 256 | echo "[Error]: Build directory not found : ${build_dir}" && exit 1 257 | fi 258 | 259 | cd ${build_dir} 260 | 261 | timed_message "Testing CHAI" 262 | ctest --output-on-failure --no-compress-output -T test -VV 2>&1 | tee tests_output.txt 263 | 264 | no_test_str="No tests were found!!!" 265 | if [[ "$(tail -n 1 tests_output.txt)" == "${no_test_str}" ]] 266 | then 267 | echo "[Error]: No tests were found" && exit 1 268 | fi 269 | 270 | timed_message "Preparing tests xml reports for export" 271 | tree Testing 272 | xsltproc -o junit.xml ${project_dir}/scripts/radiuss-spack-configs/utilities/ctest-to-junit.xsl Testing/*/Test.xml 273 | mv junit.xml ${project_dir}/junit.xml 274 | 275 | if grep -q "Errors while running CTest" ./tests_output.txt 276 | then 277 | echo "[Error]: Failure(s) while running CTest" && exit 1 278 | fi 279 | 280 | if grep -q -i "ENABLE_HIP.*ON" ${hostconfig_path} 281 | then 282 | echo "[Warning]: Not testing install with HIP" 283 | else 284 | if [[ ! -d ${install_dir} ]] 285 | then 286 | echo "[Error]: Install directory not found : ${install_dir}" && exit 1 287 | fi 288 | 289 | cd ${install_dir}/examples/chai/using-with-cmake 290 | mkdir build && cd build 291 | if ! $cmake_exe -C ../host-config.cmake ..; then 292 | echo "[Error]: Running $cmake_exe for using-with-cmake test" && exit 1 293 | fi 294 | 295 | if ! make; then 296 | echo "[Error]: Running make for using-with-cmake test" && exit 1 297 | fi 298 | fi 299 | 300 | timed_message "CHAI tests completed" 301 | fi 302 | 303 | timed_message "Cleaning up" 304 | make clean 305 | 306 | timed_message "Build and test completed" 307 | -------------------------------------------------------------------------------- /scripts/license.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 8 | project contributors. See the CHAI LICENSE file for details. 9 | 10 | SPDX-License-Identifier: BSD-3-Clause 11 | -------------------------------------------------------------------------------- /scripts/make_release_tarball.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 4 | # project contributors. See the CHAI LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: BSD-3-Clause 7 | ############################################################################## 8 | 9 | TAR_CMD=gtar 10 | VERSION=2025.03.0 11 | 12 | git archive --prefix=chai-${VERSION}/ -o chai-${VERSION}.tar HEAD 2> /dev/null 13 | 14 | echo "Running git archive submodules..." 15 | 16 | p=`pwd` && (echo .; git submodule foreach --recursive) | while read entering path; do 17 | temp="${path%\'}"; 18 | temp="${temp#\'}"; 19 | path=$temp; 20 | [ "$path" = "" ] && continue; 21 | (cd $path && git archive --prefix=chai-${VERSION}/$path/ HEAD > $p/tmp.tar && ${TAR_CMD} --concatenate --file=$p/chai-${VERSION}.tar $p/tmp.tar && rm $p/tmp.tar); 22 | done 23 | 24 | gzip chai-${VERSION}.tar 25 | -------------------------------------------------------------------------------- /scripts/travis/build_and_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 4 | # project contributors. See the CHAI LICENSE file for details. 5 | # 6 | # SPDX-License-Identifier: BSD-3-Clause 7 | ############################################################################## 8 | 9 | function or_die () { 10 | "$@" 11 | local status=$? 12 | if [[ $status != 0 ]] ; then 13 | echo ERROR $status command: $@ 14 | exit $status 15 | fi 16 | } 17 | 18 | threads=3 19 | top_dir=$(pwd) 20 | travis_build_dir=${top_dir}/travis-build 21 | travis_install_dir=${top_dir}/travis-install 22 | 23 | or_die mkdir $travis_build_dir 24 | or_die mkdir $travis_install_dir 25 | 26 | if [[ "$DO_BUILD" == "yes" ]] ; then 27 | or_die cd $travis_build_dir 28 | or_die cmake -DCMAKE_CXX_COMPILER="${COMPILER}" ${CMAKE_EXTRA_FLAGS} -DCMAKE_INSTALL_PREFIX=$travis_install_dir ../ 29 | or_die make -j $threads VERBOSE=1 30 | or_die make install 31 | if [[ "${DO_TEST}" == "yes" ]] ; then 32 | or_die ctest -V 33 | fi 34 | fi 35 | 36 | if [[ "$BUILD_RAJA" == "yes" ]] ; then 37 | or_die cd $top_dir 38 | or_die git clone --recursive -b develop https://github.com/LLNL/RAJA.git 39 | or_die cd RAJA 40 | or_die mkdir build 41 | or_die cd build 42 | or_die cmake -DCMAKE_CXX_COMPILER="${COMPILER}" ${CMAKE_EXTRA_FLAGS} -DENABLE_CHAI=On -Dchai_DIR=${travis_install_dir}/share/chai/cmake ../ 43 | or_die make -j $threads VERBOSE=2 44 | fi 45 | 46 | exit 0 47 | -------------------------------------------------------------------------------- /scripts/travis/install_llvm.sh: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | # /bin/bash 8 | 9 | export LLVM_PATH=${HOME}/llvm/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04 10 | export PATH=${LLVM_PATH}/bin:${PATH} 11 | export LD_LIBRARY_PATH=${LLVM_PATH}/lib:${LD_LIBRARY_PATH} 12 | export DOWNLOAD_URL=http://releases.llvm.org/${LLVM_VERSION}/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz 13 | export TARFILE=${HOME}/download/llvm-${LLVM_VERSION}.tar.xz 14 | if ! [[ -d "${LLVM_PATH}" ]]; then 15 | if ! [[ -f ${TARFILE} ]]; then 16 | echo "curl -o ${TARFILE} ${DOWNLOAD_URL}" 17 | curl -o ${TARFILE} ${DOWNLOAD_URL} 18 | fi 19 | cd ${HOME}/llvm 20 | tar xf ${TARFILE} 21 | fi 22 | -------------------------------------------------------------------------------- /scripts/update-copyright.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 5 | # project contributors. See the CHAI LICENSE file for details. 6 | # 7 | # SPDX-License-Identifier: (MIT) 8 | ############################################################################## 9 | 10 | #============================================================================= 11 | # Change the copyright date in all files that contain the text 12 | # "the CHAI LICENSE file", which is part of the copyright statement at the 13 | # top of each CHAI file. We use this to distinguish CHAI files from ones 14 | # that we do not own (e.g., other repos included as submodules), which we 15 | # do not want to modify. Note that this file and *.git files are omitted 16 | # as well. 17 | # 18 | # IMPORTANT: Since this file is not modified (it is running the shell 19 | # script commands), you must EDIT THE COPYRIGHT DATES IN THE HEADER ABOVE 20 | # MANUALLY. 21 | # 22 | # Edit the 'grep' command below to change the set of files that will be 23 | # modified. 24 | # 25 | # Change the 'sed' command below to change the content that is changed 26 | # in each file and what it is changed to. Typically, this would only be 27 | # modifying the end year in the copyright date. 28 | # 29 | #============================================================================= 30 | # 31 | # If you need to modify this script, you may want to run each of these 32 | # commands individually from the command line to make sure things are doing 33 | # what you think they should be doing. This is why they are separated into 34 | # steps here. 35 | # 36 | #============================================================================= 37 | 38 | #============================================================================= 39 | # First find all the files we want to modify 40 | #============================================================================= 41 | grep -rl "the CHAI LICENSE file" . --exclude-dir=.git --exclude-dir=blt --exclude-dir=umpire --exclude-dir=raja --exclude-dir=radiuss-spack-configs --exclude-dir=uberenv --exclude=update-copyright.sh > files2change 42 | 43 | #============================================================================= 44 | # Replace the old copyright dates with new dates 45 | #============================================================================= 46 | for i in `cat files2change` 47 | do 48 | echo $i 49 | cp $i $i.sed.bak 50 | sed "s/Copyright (c) \([0-9]\{4\}\)-[0-9]\{2\},/Copyright (c) 2016-25,/" $i.sed.bak > $i 51 | done 52 | 53 | echo LICENSE 54 | cp LICENSE LICENSE.sed.bak 55 | sed "s/Copyright (c) \([0-9]\{4\}\)-[0-9]\{4\}/Copyright (c) 2016-25/" LICENSE.sed.bak > LICENSE 56 | 57 | for i in README.md CONTRIBUTING.md 58 | do 59 | echo $i 60 | cp $i $i.sed.bak 61 | sed "s/\([0-9]\{4\}\)-[0-9]\{2\}/2016-25/" $i.sed.bak > $i 62 | done 63 | 64 | #============================================================================= 65 | # Remove temporary files created in the process 66 | #============================================================================= 67 | find . -name \*.sed.bak -exec rm {} \; 68 | rm files2change 69 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | add_subdirectory(chai) 8 | -------------------------------------------------------------------------------- /src/chai/ArrayManager.inl: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_ArrayManager_INL 8 | #define CHAI_ArrayManager_INL 9 | 10 | #include "chai/config.hpp" 11 | 12 | #include "chai/ArrayManager.hpp" 13 | #include "chai/ChaiMacros.hpp" 14 | 15 | #include 16 | 17 | #include "umpire/ResourceManager.hpp" 18 | 19 | #if defined(CHAI_ENABLE_UM) 20 | #if !defined(CHAI_THIN_GPU_ALLOCATE) 21 | #include 22 | #endif 23 | #endif 24 | 25 | namespace chai { 26 | 27 | template 28 | CHAI_INLINE 29 | void* ArrayManager::reallocate(void* pointer, size_t elems, PointerRecord* pointer_record) 30 | { 31 | ExecutionSpace my_space = CPU; 32 | 33 | for (int iSpace = CPU; iSpace < NUM_EXECUTION_SPACES; ++iSpace) { 34 | if (pointer_record->m_pointers[iSpace] == pointer) { 35 | my_space = static_cast(iSpace); 36 | break; 37 | } 38 | } 39 | 40 | for (int iSpace = CPU; iSpace < NUM_EXECUTION_SPACES; ++iSpace) { 41 | if (!pointer_record->m_owned[iSpace]) { 42 | CHAI_LOG(Debug, "Cannot reallocate unowned pointer"); 43 | return pointer_record->m_pointers[my_space]; 44 | } 45 | } 46 | 47 | // Call callback with ACTION_FREE before changing the size 48 | for (int iSpace = CPU; iSpace < NUM_EXECUTION_SPACES; ++iSpace) { 49 | void* space_ptr = pointer_record->m_pointers[iSpace]; 50 | int actualSpace = iSpace; 51 | if (space_ptr) { 52 | #if defined(CHAI_ENABLE_UM) 53 | if (space_ptr == pointer_record->m_pointers[UM]) { 54 | actualSpace = UM; 55 | } else 56 | #endif 57 | #if defined(CHAI_ENABLE_PINNED) 58 | if (space_ptr == pointer_record->m_pointers[PINNED]) { 59 | actualSpace = PINNED; 60 | } 61 | #endif 62 | callback(pointer_record, ACTION_FREE, ExecutionSpace(actualSpace)); 63 | if (actualSpace == UM || actualSpace == PINNED) { 64 | // stop the loop over spaces 65 | break; 66 | } 67 | } 68 | } 69 | 70 | // Update the pointer record size 71 | size_t old_size = pointer_record->m_size; 72 | size_t new_size = sizeof(T) * elems; 73 | pointer_record->m_size = new_size; 74 | 75 | // only copy however many bytes overlap 76 | size_t num_bytes_to_copy = std::min(old_size, new_size); 77 | 78 | for (int iSpace = CPU; iSpace < NUM_EXECUTION_SPACES; ++iSpace) { 79 | void* space_ptr = pointer_record->m_pointers[iSpace]; 80 | auto alloc = m_resource_manager.getAllocator(pointer_record->m_allocators[iSpace]); 81 | int actualSpace = iSpace; 82 | 83 | if (space_ptr) { 84 | #if defined(CHAI_ENABLE_UM) 85 | if (space_ptr == pointer_record->m_pointers[UM]) { 86 | alloc = m_resource_manager.getAllocator(pointer_record->m_allocators[UM]); 87 | actualSpace = UM; 88 | } else 89 | #endif 90 | #if defined(CHAI_ENABLE_PINNED) 91 | if (space_ptr == pointer_record->m_pointers[PINNED]) { 92 | alloc = m_resource_manager.getAllocator(pointer_record->m_allocators[PINNED]); 93 | actualSpace = PINNED; 94 | } else 95 | #endif 96 | { 97 | alloc = m_resource_manager.getAllocator(pointer_record->m_allocators[iSpace]); 98 | } 99 | void* new_ptr = alloc.allocate(new_size); 100 | #if CHAI_ENABLE_ZERO_INITIALIZED_MEMORY 101 | m_resource_manager.memset(new_ptr, 0, new_size); 102 | #endif 103 | m_resource_manager.copy(new_ptr, space_ptr, num_bytes_to_copy); 104 | alloc.deallocate(space_ptr); 105 | 106 | pointer_record->m_pointers[actualSpace] = new_ptr; 107 | callback(pointer_record, ACTION_ALLOC, ExecutionSpace(actualSpace)); 108 | 109 | m_pointer_map.erase(space_ptr); 110 | m_pointer_map.insert(new_ptr, pointer_record); 111 | 112 | if (actualSpace == UM || actualSpace == PINNED) { 113 | for (int aliasedSpace = CPU; aliasedSpace < NUM_EXECUTION_SPACES; ++aliasedSpace) { 114 | if (aliasedSpace != UM && aliasedSpace != PINNED) { 115 | pointer_record->m_pointers[aliasedSpace] = new_ptr; 116 | } 117 | } 118 | // stop the loop over spaces 119 | break; 120 | } 121 | } 122 | } 123 | 124 | return pointer_record->m_pointers[my_space]; 125 | } 126 | 127 | template 128 | CHAI_INLINE 129 | typename ArrayManager::T_non_const ArrayManager::pick(T* src_ptr, size_t index) 130 | { 131 | T_non_const val; 132 | m_resource_manager.registerAllocation(const_cast*>(&val), umpire::util::AllocationRecord{const_cast*>(&val), sizeof(T), m_resource_manager.getAllocator("HOST").getAllocationStrategy()}); 133 | m_resource_manager.copy(const_cast*>(&val), const_cast*>(src_ptr+index), sizeof(T)); 134 | m_resource_manager.deregisterAllocation(&val); 135 | return val; 136 | } 137 | 138 | template 139 | CHAI_INLINE 140 | void ArrayManager::set(T* dst_ptr, size_t index, const T& val) 141 | { 142 | m_resource_manager.registerAllocation(const_cast*>(&val), umpire::util::AllocationRecord{const_cast*>(&val), sizeof(T), m_resource_manager.getAllocator("HOST").getAllocationStrategy()}); 143 | m_resource_manager.copy(const_cast*>(dst_ptr+index), const_cast*>(&val), sizeof(T)); 144 | m_resource_manager.deregisterAllocation(const_cast*>(&val)); 145 | } 146 | 147 | CHAI_INLINE 148 | void ArrayManager::copy(void * dst, void * src, size_t size) { 149 | m_resource_manager.copy(dst,src,size); 150 | } 151 | 152 | CHAI_INLINE 153 | umpire::Allocator ArrayManager::getAllocator(ExecutionSpace space) { 154 | return *m_allocators[space]; 155 | } 156 | 157 | CHAI_INLINE 158 | umpire::Allocator ArrayManager::getAllocator(int allocator_id) { 159 | return m_resource_manager.getAllocator(allocator_id); 160 | } 161 | 162 | CHAI_INLINE 163 | void ArrayManager::setAllocator(ExecutionSpace space, umpire::Allocator &allocator) { 164 | *m_allocators[space] = allocator; 165 | } 166 | 167 | CHAI_INLINE 168 | bool ArrayManager::syncIfNeeded() { 169 | if (!m_synced_since_last_kernel) { 170 | synchronize(); 171 | m_synced_since_last_kernel = true; 172 | return true; 173 | } 174 | return false; 175 | } 176 | } // end of namespace chai 177 | 178 | #endif // CHAI_ArrayManager_INL 179 | -------------------------------------------------------------------------------- /src/chai/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | 8 | include(CMakePackageConfigHelpers) 9 | 10 | configure_file( 11 | ${PROJECT_SOURCE_DIR}/src/chai/config.hpp.in 12 | ${PROJECT_BINARY_DIR}/include/chai/config.hpp) 13 | 14 | set (chai_headers 15 | ArrayManager.hpp 16 | ArrayManager.inl 17 | ChaiMacros.hpp 18 | ExecutionSpaces.hpp 19 | ManagedArray.hpp 20 | ManagedArray.inl 21 | managed_ptr.hpp 22 | PointerRecord.hpp 23 | Types.hpp) 24 | 25 | if(CHAI_DISABLE_RM) 26 | set(chai_headers 27 | ${chai_headers} 28 | ManagedArray_thin.inl) 29 | endif () 30 | 31 | set (chai_sources 32 | ArrayManager.cpp) 33 | 34 | set (chai_depends 35 | umpire) 36 | 37 | if (CHAI_ENABLE_CUDA) 38 | set (chai_depends 39 | ${chai_depends} 40 | cuda_runtime) 41 | endif () 42 | if (CHAI_ENABLE_HIP) 43 | set (chai_depends 44 | ${chai_depends} 45 | blt::hip_runtime) 46 | endif () 47 | 48 | if (CHAI_ENABLE_RAJA_PLUGIN) 49 | set (chai_headers 50 | ${chai_headers} 51 | pluginLinker.hpp 52 | ManagedArrayView.hpp 53 | RajaExecutionSpacePlugin.hpp) 54 | 55 | set (chai_sources 56 | ${chai_sources} 57 | RajaExecutionSpacePlugin.cpp) 58 | 59 | set (chai_depends 60 | ${chai_depends} 61 | RAJA) 62 | 63 | if (CHAI_ENABLE_CUDA) 64 | set (chai_depends 65 | ${chai_depends} 66 | cuda) 67 | endif () 68 | endif () 69 | 70 | blt_add_library( 71 | NAME chai 72 | SOURCES ${chai_sources} 73 | HEADERS ${chai_headers} 74 | DEPENDS_ON ${chai_depends}) 75 | 76 | install(FILES ${chai_headers} DESTINATION include/chai/) 77 | 78 | install(FILES ../util/forall.hpp DESTINATION include/chai/util/) 79 | 80 | target_include_directories( 81 | chai 82 | PUBLIC 83 | $ 84 | $ 85 | $) 86 | 87 | configure_package_config_file( 88 | ${PROJECT_SOURCE_DIR}/cmake/chai-config.cmake.in 89 | ${PROJECT_BINARY_DIR}/chai-config.cmake 90 | INSTALL_DESTINATION lib/cmake/chai) 91 | 92 | install( 93 | FILES ${PROJECT_BINARY_DIR}/chai-config.cmake 94 | DESTINATION lib/cmake/chai) 95 | 96 | write_basic_package_version_file( 97 | ${PROJECT_BINARY_DIR}/chai-config-version.cmake 98 | COMPATIBILITY SameMajorVersion) 99 | 100 | install(FILES 101 | ${PROJECT_BINARY_DIR}/chai-config-version.cmake 102 | DESTINATION lib/cmake/chai) 103 | 104 | install( 105 | FILES ${PROJECT_BINARY_DIR}/include/chai/config.hpp 106 | DESTINATION include/chai) 107 | 108 | install( 109 | FILES ${chai_headers} 110 | DESTINATION include/chai) 111 | 112 | install( 113 | TARGETS chai 114 | EXPORT chai-targets 115 | RUNTIME DESTINATION lib 116 | LIBRARY DESTINATION lib 117 | ARCHIVE DESTINATION lib) 118 | 119 | install(EXPORT chai-targets DESTINATION lib/cmake/chai) 120 | 121 | blt_install_tpl_setups(DESTINATION lib/cmake/chai) 122 | -------------------------------------------------------------------------------- /src/chai/ChaiMacros.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_ChaiMacros_HPP 8 | #define CHAI_ChaiMacros_HPP 9 | 10 | #include "chai/config.hpp" 11 | 12 | #include "umpire/util/Macros.hpp" 13 | 14 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 15 | #define CHAI_ENABLE_DEVICE 16 | #endif 17 | 18 | #if defined(CHAI_ENABLE_CUDA) 19 | 20 | #include 21 | 22 | #define CHAI_HOST __host__ 23 | #define CHAI_DEVICE __device__ 24 | #define CHAI_HOST_DEVICE __device__ __host__ 25 | #define CHAI_GLOBAL __global__ 26 | 27 | #define gpuMemcpyKind cudaMemcpyKind 28 | #define gpuMemcpyHostToHost cudaMemcpyHostToHost 29 | #define gpuMemcpyHostToDevice cudaMemcpyHostToDevice 30 | #define gpuMemcpyDeviceToHost cudaMemcpyDeviceToHost 31 | #define gpuMemcpyDeviceToDevice cudaMemcpyDeviceToDevice 32 | #define gpuMemcpyDefault cudaMemcpyDefault 33 | 34 | // NOTE: Cannot have if defined(__HIPCC__) in the condition below, since __HIPCC__ comes from the included header hip_runtime below. 35 | #elif defined(CHAI_ENABLE_HIP) 36 | 37 | #include 38 | 39 | #define CHAI_HOST __host__ 40 | #define CHAI_DEVICE __device__ 41 | #define CHAI_HOST_DEVICE __device__ __host__ 42 | #define CHAI_GLOBAL __global__ 43 | 44 | #define gpuMemcpyKind hipMemcpyKind 45 | #define gpuMemcpyHostToHost hipMemcpyHostToHost 46 | #define gpuMemcpyHostToDevice hipMemcpyHostToDevice 47 | #define gpuMemcpyDeviceToHost hipMemcpyDeviceToHost 48 | #define gpuMemcpyDeviceToDevice hipMemcpyDeviceToDevice 49 | #define gpuMemcpyDefault hipMemcpyDefault 50 | 51 | #else 52 | 53 | #define CHAI_HOST 54 | #define CHAI_DEVICE 55 | #define CHAI_HOST_DEVICE 56 | #define CHAI_GLOBAL 57 | 58 | #define gpuMemcpyKind int 59 | #define gpuMemcpyHostToHost 0 60 | #define gpuMemcpyHostToDevice 1 61 | #define gpuMemcpyDeviceToHost 2 62 | #define gpuMemcpyDeviceToDevice 3 63 | #define gpuMemcpyDefault 4 64 | 65 | #endif 66 | 67 | #if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__) 68 | #define CHAI_DEVICE_COMPILE 69 | #endif 70 | 71 | // shorthand for GPU Compilation. Must go after hip/hip_runtime.h is included so that HIPCC is defined 72 | #if defined(__CUDACC__) || defined(__HIPCC__) 73 | #define CHAI_GPUCC 74 | #endif 75 | 76 | #define CHAI_INLINE inline 77 | 78 | #define CHAI_UNUSED_ARG(X) 79 | 80 | #if !defined(CHAI_DISABLE_RM) 81 | 82 | #define CHAI_LOG(level, msg) \ 83 | UMPIRE_LOG(level, msg); 84 | 85 | #else 86 | 87 | #if defined(CHAI_DEBUG) 88 | 89 | #define CHAI_LOG(level, msg) \ 90 | std::cerr << "[" << __FILE__ << "] " << msg << std::endl; 91 | 92 | #else 93 | 94 | #define CHAI_LOG(level, msg) 95 | 96 | #endif 97 | #endif 98 | 99 | namespace chai 100 | { 101 | template 102 | CHAI_HOST_DEVICE CHAI_INLINE void CHAI_UNUSED_VAR(T &&...) noexcept {} 103 | } // namespace chai 104 | 105 | #endif // CHAI_ChaiMacros_HPP 106 | -------------------------------------------------------------------------------- /src/chai/ExecutionSpaces.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_ExecutionSpaces_HPP 8 | #define CHAI_ExecutionSpaces_HPP 9 | 10 | #include "chai/config.hpp" 11 | 12 | namespace chai 13 | { 14 | 15 | /*! 16 | * \brief Enum listing possible execution spaces. 17 | */ 18 | enum ExecutionSpace { 19 | /*! Default, no execution space. */ 20 | NONE = 0, 21 | /*! Executing in CPU space */ 22 | CPU, 23 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) || defined(CHAI_ENABLE_GPU_SIMULATION_MODE) 24 | /*! Execution in GPU space */ 25 | GPU, 26 | #endif 27 | #if defined(CHAI_ENABLE_UM) 28 | UM, 29 | #endif 30 | #if defined(CHAI_ENABLE_PINNED) 31 | PINNED, 32 | #endif 33 | // NUM_EXECUTION_SPACES should always be last! 34 | /*! Used to count total number of spaces */ 35 | NUM_EXECUTION_SPACES 36 | #if !defined(CHAI_ENABLE_CUDA) && !defined(CHAI_ENABLE_HIP) && !defined(CHAI_ENABLE_GPU_SIMULATION_MODE) 37 | ,GPU 38 | #endif 39 | #if !defined(CHAI_ENABLE_UM) 40 | ,UM 41 | #endif 42 | #if !defined(CHAI_ENABLE_PINNED) 43 | ,PINNED 44 | #endif 45 | }; 46 | 47 | } // end of namespace chai 48 | 49 | #endif // CHAI_ExecutionSpaces_HPP 50 | -------------------------------------------------------------------------------- /src/chai/ManagedArrayView.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_ManagedArrayView_HPP 8 | #define CHAI_ManagedArrayView_HPP 9 | 10 | #include "chai/config.hpp" 11 | 12 | #if defined(CHAI_ENABLE_RAJA_PLUGIN) 13 | 14 | #include "chai/ManagedArray.hpp" 15 | 16 | #include "RAJA/util/View.hpp" 17 | 18 | namespace chai { 19 | 20 | template 21 | using ManagedArrayView = 22 | RAJA::View>; 23 | 24 | 25 | template 26 | using TypedManagedArrayView = RAJA::internal::TypedViewBase, 28 | LayoutType, 29 | camp::list >; 30 | 31 | template 32 | using ManagedArrayMultiView = 33 | RAJA::MultiView *, 37 | chai::ManagedArray> *>; 38 | 39 | } // end of namespace chai 40 | 41 | #endif // defined(CHAI_ENABLE_RAJA_PLUGIN) 42 | 43 | #endif // CHAI_ManagedArrayView_HPP 44 | -------------------------------------------------------------------------------- /src/chai/PointerRecord.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_PointerRecord_HPP 8 | #define CHAI_PointerRecord_HPP 9 | 10 | #include "chai/ExecutionSpaces.hpp" 11 | #include "chai/Types.hpp" 12 | 13 | #include 14 | #include 15 | 16 | namespace chai 17 | { 18 | 19 | /*! 20 | * \brief Struct holding details about each pointer. 21 | */ 22 | struct PointerRecord { 23 | /*! 24 | * Size of pointer allocation in bytes 25 | */ 26 | std::size_t m_size; 27 | 28 | /*! 29 | * Array holding the pointer in each execution space. 30 | */ 31 | void* m_pointers[NUM_EXECUTION_SPACES]; 32 | 33 | /*! 34 | * Array holding touched state of pointer in each execution space. 35 | */ 36 | bool m_touched[NUM_EXECUTION_SPACES]; 37 | 38 | /*! 39 | * Execution space where this arary was last touched. 40 | */ 41 | ExecutionSpace m_last_space; 42 | 43 | /*! 44 | * Array holding ownership status of each pointer. 45 | */ 46 | bool m_owned[NUM_EXECUTION_SPACES]; 47 | 48 | 49 | /*! 50 | * User defined callback triggered on memory operations. 51 | * 52 | * Function is passed the execution space that the memory is 53 | * moved to, and the number of bytes moved. 54 | */ 55 | UserCallback m_user_callback; 56 | 57 | int m_allocators[NUM_EXECUTION_SPACES]; 58 | 59 | /*! 60 | * \brief Default constructor 61 | * 62 | */ 63 | PointerRecord() : m_size(0), m_last_space(NONE) { 64 | m_user_callback = [] (const PointerRecord*, Action, ExecutionSpace) {}; 65 | for (int space = 0; space < NUM_EXECUTION_SPACES; ++space ) { 66 | m_pointers[space] = nullptr; 67 | m_touched[space] = false; 68 | m_owned[space] = true; 69 | m_allocators[space] = 0; 70 | } 71 | } 72 | }; 73 | 74 | } // end of namespace chai 75 | 76 | #endif // CHAI_PointerRecord_HPP 77 | -------------------------------------------------------------------------------- /src/chai/RajaExecutionSpacePlugin.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "chai/config.hpp" 8 | 9 | #include "chai/RajaExecutionSpacePlugin.hpp" 10 | 11 | #include "chai/ArrayManager.hpp" 12 | 13 | namespace chai { 14 | 15 | RajaExecutionSpacePlugin::RajaExecutionSpacePlugin() 16 | { 17 | } 18 | 19 | void 20 | RajaExecutionSpacePlugin::preCapture(const RAJA::util::PluginContext& p) 21 | { 22 | if (!m_arraymanager) { 23 | m_arraymanager = chai::ArrayManager::getInstance(); 24 | } 25 | 26 | switch (p.platform) { 27 | case RAJA::Platform::host: 28 | m_arraymanager->setExecutionSpace(chai::CPU); break; 29 | #if defined(CHAI_ENABLE_CUDA) 30 | case RAJA::Platform::cuda: 31 | m_arraymanager->setExecutionSpace(chai::GPU); break; 32 | #endif 33 | #if defined(CHAI_ENABLE_HIP) 34 | case RAJA::Platform::hip: 35 | m_arraymanager->setExecutionSpace(chai::GPU); break; 36 | #endif 37 | default: 38 | m_arraymanager->setExecutionSpace(chai::NONE); 39 | } 40 | } 41 | 42 | void 43 | RajaExecutionSpacePlugin::postCapture(const RAJA::util::PluginContext&) 44 | { 45 | m_arraymanager->setExecutionSpace(chai::NONE); 46 | } 47 | 48 | } 49 | RAJA_INSTANTIATE_REGISTRY(RAJA::util::PluginRegistry); 50 | 51 | // this is needed to link a dynamic lib as RAJA does not provide an exported definition of this symbol. 52 | #if defined(_WIN32) && !defined(CHAISTATICLIB) 53 | #ifdef CHAISHAREDDLL_EXPORTS 54 | namespace RAJA 55 | { 56 | namespace util 57 | { 58 | 59 | PluginStrategy::PluginStrategy() = default; 60 | 61 | } // namespace util 62 | } // namespace RAJA 63 | #endif 64 | #endif 65 | 66 | // Register plugin with RAJA 67 | RAJA::util::PluginRegistry::add P( 68 | "RajaExecutionSpacePlugin", 69 | "Plugin to set CHAI execution space based on RAJA execution platform"); 70 | 71 | 72 | namespace chai { 73 | 74 | void linkRajaPlugin() {} 75 | 76 | } 77 | 78 | -------------------------------------------------------------------------------- /src/chai/RajaExecutionSpacePlugin.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_RajaExecutionSpacePlugin_HPP 8 | #define CHAI_RajaExecutionSpacePlugin_HPP 9 | 10 | #include "RAJA/util/PluginStrategy.hpp" 11 | 12 | namespace chai { 13 | 14 | class ArrayManager; 15 | 16 | class RajaExecutionSpacePlugin : 17 | public RAJA::util::PluginStrategy 18 | { 19 | public: 20 | RajaExecutionSpacePlugin(); 21 | 22 | void preCapture(const RAJA::util::PluginContext& p) override; 23 | 24 | void postCapture(const RAJA::util::PluginContext& p) override; 25 | 26 | private: 27 | chai::ArrayManager* m_arraymanager{nullptr}; 28 | }; 29 | 30 | void linkRajaPlugin(); 31 | 32 | } 33 | 34 | #endif // CHAI_RajaExecutionSpacePlugin_HPP 35 | -------------------------------------------------------------------------------- /src/chai/Types.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_Types_HPP 8 | #define CHAI_Types_HPP 9 | 10 | // Std library headers 11 | #include 12 | 13 | // CHAI headers 14 | #include "chai/ExecutionSpaces.hpp" 15 | 16 | #if defined(_WIN32) && !defined(CHAISTATICLIB) 17 | #ifdef CHAISHAREDDLL_EXPORTS 18 | #define CHAISHAREDDLL_API __declspec(dllexport) 19 | #else 20 | #define CHAISHAREDDLL_API __declspec(dllimport) 21 | #endif 22 | #else 23 | #define CHAISHAREDDLL_API 24 | #endif 25 | 26 | namespace chai 27 | { 28 | struct PointerRecord; 29 | 30 | typedef unsigned int uint; 31 | 32 | enum Action { ACTION_ALLOC, ACTION_FREE, ACTION_MOVE, ACTION_CAPTURED, ACTION_FOUND_ABANDONED, ACTION_LEAKED }; 33 | 34 | using UserCallback = std::function; 35 | } // end of namespace chai 36 | 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/chai/config.hpp.in: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_config_HPP 8 | #define CHAI_config_HPP 9 | 10 | #cmakedefine CHAI_ENABLE_CUDA 11 | #cmakedefine CHAI_ENABLE_HIP 12 | #cmakedefine CHAI_DISABLE_RM 13 | #cmakedefine CHAI_THIN_GPU_ALLOCATE 14 | #cmakedefine CHAI_ENABLE_UM 15 | #cmakedefine CHAI_DEBUG 16 | #cmakedefine CHAI_ENABLE_GPU_ERROR_CHECKING 17 | #cmakedefine CHAI_ENABLE_MANAGED_PTR 18 | #cmakedefine CHAI_ENABLE_MANAGED_PTR_ON_GPU 19 | #cmakedefine CHAI_ENABLE_RAJA_PLUGIN 20 | #cmakedefine CHAI_ENABLE_GPU_SIMULATION_MODE 21 | #cmakedefine CHAI_ENABLE_PINNED 22 | 23 | #endif // CHAI_config_HPP 24 | -------------------------------------------------------------------------------- /src/chai/pluginLinker.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_pluginLinker_HPP 8 | #define CHAI_pluginLinker_HPP 9 | 10 | #include "chai/RajaExecutionSpacePlugin.hpp" 11 | 12 | namespace { 13 | namespace anonymous_chai { 14 | struct pluginLinker { 15 | pluginLinker() { 16 | (void) chai::linkRajaPlugin(); 17 | } 18 | } pluginLinker; 19 | } 20 | } 21 | 22 | #endif // CHAI_pluginLinker_HPP 23 | -------------------------------------------------------------------------------- /src/util/forall.hpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #ifndef CHAI_forall_HPP 8 | #define CHAI_forall_HPP 9 | 10 | #include "chai/ArrayManager.hpp" 11 | #include "chai/ExecutionSpaces.hpp" 12 | #include "chai/config.hpp" 13 | 14 | #if defined(CHAI_ENABLE_UM) 15 | #if !defined(CHAI_THIN_GPU_ALLOCATE) 16 | #include 17 | #endif 18 | #endif 19 | 20 | struct sequential { 21 | }; 22 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 23 | struct gpu { 24 | }; 25 | 26 | struct gpu_async {}; 27 | #endif 28 | 29 | template 30 | void forall_kernel_cpu(int begin, int end, LOOP_BODY body) 31 | { 32 | for (int i = begin; i < end; ++i) { 33 | body(i); 34 | } 35 | } 36 | 37 | /* 38 | * \brief Run forall kernel on CPU. 39 | */ 40 | template 41 | void forall(sequential, int begin, int end, LOOP_BODY body) 42 | { 43 | chai::ArrayManager* rm = chai::ArrayManager::getInstance(); 44 | 45 | #if defined(CHAI_ENABLE_UM) 46 | #if !defined(CHAI_THIN_GPU_ALLOCATE) 47 | cudaDeviceSynchronize(); 48 | #endif 49 | #endif 50 | 51 | rm->setExecutionSpace(chai::CPU); 52 | 53 | forall_kernel_cpu(begin, end, body); 54 | 55 | rm->setExecutionSpace(chai::NONE); 56 | } 57 | 58 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 59 | template 60 | __global__ void forall_kernel_gpu(int start, int length, LOOP_BODY body) 61 | { 62 | int idx = blockDim.x * blockIdx.x + threadIdx.x; 63 | 64 | if (idx < length) { 65 | body(idx+start); 66 | } 67 | } 68 | 69 | template 70 | void forall(gpu_async, int begin, int end, LOOP_BODY&& body) 71 | { 72 | chai::ArrayManager* rm = chai::ArrayManager::getInstance(); 73 | 74 | rm->setExecutionSpace(chai::GPU); 75 | 76 | #if defined(CHAI_ENABLE_CUDA) 77 | size_t blockSize = 32; 78 | #elif defined(CHAI_ENABLE_HIP) 79 | size_t blockSize = 64; 80 | #endif 81 | 82 | size_t gridSize = (end - begin + blockSize - 1) / blockSize; 83 | 84 | #if defined(CHAI_ENABLE_GPU_SIMULATION_MODE) 85 | forall_kernel_cpu(begin, end, body); 86 | #elif defined(CHAI_ENABLE_CUDA) 87 | forall_kernel_gpu<<>>(begin, end - begin, body); 88 | #elif defined(CHAI_ENABLE_HIP) 89 | hipLaunchKernelGGL(forall_kernel_gpu, dim3(gridSize), dim3(blockSize), 0, 0, 90 | begin, end - begin, body); 91 | #endif 92 | rm->setExecutionSpace(chai::NONE); 93 | } 94 | 95 | /* 96 | * \brief Run forall kernel on GPU. 97 | */ 98 | template 99 | void forall(gpu, int begin, int end, LOOP_BODY&& body) 100 | { 101 | chai::ArrayManager* rm = chai::ArrayManager::getInstance(); 102 | 103 | rm->setExecutionSpace(chai::GPU); 104 | 105 | #if defined(CHAI_ENABLE_CUDA) 106 | size_t blockSize = 32; 107 | #elif defined(CHAI_ENABLE_HIP) 108 | size_t blockSize = 64; 109 | #endif 110 | 111 | size_t gridSize = (end - begin + blockSize - 1) / blockSize; 112 | 113 | #if defined(CHAI_ENABLE_GPU_SIMULATION_MODE) 114 | forall_kernel_cpu(begin, end, body); 115 | #elif defined(CHAI_ENABLE_CUDA) 116 | forall_kernel_gpu<<>>(begin, end - begin, body); 117 | cudaDeviceSynchronize(); 118 | #elif defined(CHAI_ENABLE_HIP) 119 | hipLaunchKernelGGL(forall_kernel_gpu, dim3(gridSize), dim3(blockSize), 0, 0, 120 | begin, end - begin, body); 121 | hipDeviceSynchronize(); 122 | #endif 123 | 124 | rm->setExecutionSpace(chai::NONE); 125 | } 126 | #endif 127 | 128 | #endif // CHAI_forall_HPP 129 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | 8 | add_subdirectory(install) 9 | add_subdirectory(unit) 10 | add_subdirectory(integration) 11 | -------------------------------------------------------------------------------- /tests/install/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC 3 | # and CHAI project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (BSD-3-Clause) 6 | ############################################################################### 7 | 8 | configure_file( 9 | using-with-cmake/host-config.cmake.in 10 | ${PROJECT_BINARY_DIR}/examples/using-with-cmake/host-config.cmake) 11 | 12 | install( FILES 13 | using-with-cmake/CMakeLists.txt 14 | using-with-cmake/using-with-cmake.cpp 15 | ${PROJECT_BINARY_DIR}/examples/using-with-cmake/host-config.cmake 16 | DESTINATION examples/chai/using-with-cmake) 17 | -------------------------------------------------------------------------------- /tests/install/using-with-cmake/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC 3 | # and CHAI project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (BSD-3-Clause) 6 | ############################################################################### 7 | 8 | if (ENABLE_HIP) 9 | cmake_minimum_required(VERSION 3.23) 10 | else() 11 | cmake_minimum_required(VERSION 3.20) 12 | endif() 13 | 14 | project(using_with_cmake) 15 | 16 | if (ENABLE_CUDA) 17 | enable_language(CUDA) 18 | endif() 19 | 20 | if (ENABLE_HIP) 21 | if (NOT ROCM_PATH) 22 | find_path(ROCM_PATH 23 | hip 24 | ENV{ROCM_DIR} 25 | ENV{ROCM_PATH} 26 | ENV{HIP_PATH} 27 | ${HIP_PATH}/.. 28 | ${HIP_ROOT_DIR}/../ 29 | ${ROCM_ROOT_DIR} 30 | /opt/rocm) 31 | endif() 32 | 33 | set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${ROCM_PATH}") 34 | find_package(hip REQUIRED CONFIG PATHS ${ROCM_PATH}) 35 | endif() 36 | 37 | find_package(chai CONFIG REQUIRED NO_DEFAULT_PATH PATHS ${chai_DIR} ${CHAI_DIR}) 38 | 39 | # Remove implicitly added link directories added by CMake that are problematic when 40 | # the default system libraries are older than the ones used by the compiler 41 | if (BLT_CMAKE_IMPLICIT_LINK_DIRECTORIES_EXCLUDE) 42 | list(REMOVE_ITEM CMAKE_C_IMPLICIT_LINK_DIRECTORIES 43 | ${BLT_CMAKE_IMPLICIT_LINK_DIRECTORIES_EXCLUDE}) 44 | list(REMOVE_ITEM CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES 45 | ${BLT_CMAKE_IMPLICIT_LINK_DIRECTORIES_EXCLUDE}) 46 | list(REMOVE_ITEM CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES 47 | ${BLT_CMAKE_IMPLICIT_LINK_DIRECTORIES_EXCLUDE}) 48 | endif () 49 | 50 | add_executable(using-with-cmake using-with-cmake.cpp) 51 | target_link_libraries(using-with-cmake chai) 52 | -------------------------------------------------------------------------------- /tests/install/using-with-cmake/host-config.cmake.in: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC 3 | # and CHAI project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: (BSD-3-Clause) 6 | ############################################################################### 7 | 8 | # Config related to compiler 9 | set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@" CACHE PATH "") 10 | set(CMAKE_CXX_COMPILER "@CMAKE_CXX_COMPILER@" CACHE PATH "") 11 | set(CMAKE_Fortran_COMPILER "@CMAKE_Fortran_COMPILER@" CACHE PATH "") 12 | set(CMAKE_CXX_STANDARD "@CMAKE_CXX_STANDARD@" CACHE STRING "") 13 | 14 | set(CMAKE_C_FLAGS "@CMAKE_C_FLAGS@" CACHE STRING "") 15 | set(CMAKE_CXX_FLAGS "@CMAKE_CXX_FLAGS@" CACHE STRING "") 16 | set(CMAKE_Fortran_FLAGS "@CMAKE_Fortran_FLAGS@" CACHE STRING "") 17 | set(CMAKE_EXE_LINKER_FLAGS "@CMAKE_EXE_LINKER_FLAGS@" CACHE STRING "") 18 | 19 | set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE CACHE BOOL "") 20 | 21 | set(BLT_CMAKE_IMPLICIT_LINK_DIRECTORIES_EXCLUDE "@BLT_CMAKE_IMPLICIT_LINK_DIRECTORIES_EXCLUDE@" CACHE STRING "") 22 | 23 | # MPI 24 | set(ENABLE_MPI @ENABLE_MPI@ CACHE BOOL "") 25 | set(MPI_C_COMPILER "@MPI_C_COMPILER@" CACHE PATH "") 26 | set(MPI_CXX_COMPILER "@MPI_CXX_COMPILER@" CACHE PATH "") 27 | set(MPI_Fortran_COMPILER "@MPI_Fortran_COMPILER@" CACHE PATH "") 28 | set(MPIEXEC_EXECUTABLE "@MPIEXEC_EXECUTABLE@" CACHE PATH "") 29 | set(MPIEXEC_NUMPROC_FLAG "@MPIEXEC_NUMPROC_FLAG@" CACHE STRING "") 30 | 31 | # CUDA 32 | set(ENABLE_CUDA @ENABLE_CUDA@ CACHE BOOL "") 33 | 34 | if(ENABLE_CUDA) 35 | set(CUDA_TOOLKIT_ROOT_DIR "@CUDA_TOOLKIT_ROOT_DIR@" CACHE PATH "") 36 | set(CMAKE_CUDA_COMPILER "@CMAKE_CUDA_COMPILER@" CACHE PATH "") 37 | set(CMAKE_CUDA_STANDARD "@CMAKE_CUDA_STANDARD@" CACHE STRING "") 38 | set(CMAKE_CUDA_HOST_COMPILER "@CMAKE_CUDA_HOST_COMPILER@" CACHE PATH "") 39 | set(CMAKE_CUDA_SEPARABLE_COMPILATION @CMAKE_CUDA_SEPARABLE_COMPILATION@ CACHE BOOL "") 40 | set(CMAKE_CUDA_ARCHITECTURES "@CMAKE_CUDA_ARCHITECTURES@" CACHE STRING "") 41 | set(CMAKE_CUDA_FLAGS "@CMAKE_CUDA_FLAGS@" CACHE STRING "") 42 | endif() 43 | 44 | # HIP 45 | set(ENABLE_HIP @ENABLE_HIP@ CACHE BOOL "") 46 | 47 | if(ENABLE_HIP) 48 | set(HIP_ROOT_DIR "@HIP_ROOT_DIR@" CACHE PATH "") 49 | set(HIP_CLANG_PATH "@HIP_CLANG_PATH@" CACHE PATH "") 50 | set(CMAKE_HIP_ARCHITECTURES "@CMAKE_HIP_ARCHITECTURES@" CACHE STRING "") 51 | set(CMAKE_EXE_LINKER_FLAGS "@CMAKE_EXE_LINKER_FLAGS@" CACHE STRING "") 52 | endif() 53 | 54 | set(CHAI_DIR "@CMAKE_INSTALL_PREFIX@" CACHE PATH "") 55 | -------------------------------------------------------------------------------- /tests/install/using-with-cmake/using-with-cmake.cpp: -------------------------------------------------------------------------------- 1 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC 3 | // and CHAI project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: (BSD-3-Clause) 6 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// 7 | 8 | #include "chai/ManagedArray.hpp" 9 | #include 10 | 11 | int main(int, char**) 12 | { 13 | constexpr std::size_t N{1024}; 14 | chai::ManagedArray a(N); 15 | 16 | for (std::size_t i = 0; i < N; i++) { 17 | a[i] = i; 18 | } 19 | 20 | a.free(); 21 | } 22 | -------------------------------------------------------------------------------- /tests/integration/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | set (chai_integration_test_depends 8 | chai umpire gtest) 9 | 10 | blt_list_append(TO chai_integration_test_depends ELEMENTS cuda IF ${CHAI_ENABLE_CUDA}) 11 | blt_list_append(TO chai_integration_test_depends ELEMENTS blt::hip IF ${CHAI_ENABLE_HIP}) 12 | blt_list_append(TO chai_integration_test_depends ELEMENTS openmp IF ${CHAI_ENABLE_OPENMP}) 13 | 14 | # ManagedArray tests 15 | blt_add_executable( 16 | NAME managed_array_tests 17 | SOURCES managed_array_tests.cpp 18 | DEPENDS_ON ${chai_integration_test_depends}) 19 | 20 | target_include_directories( 21 | managed_array_tests 22 | PUBLIC ${PROJECT_BINARY_DIR}/include) 23 | 24 | blt_add_test( 25 | NAME managed_array_test 26 | COMMAND managed_array_tests) 27 | 28 | if (CHAI_ENABLE_MANAGED_PTR) 29 | blt_add_executable( 30 | NAME managed_ptr_tests 31 | SOURCES managed_ptr_tests.cpp 32 | DEPENDS_ON ${chai_integration_test_depends}) 33 | 34 | target_include_directories( 35 | managed_ptr_tests 36 | PUBLIC ${PROJECT_BINARY_DIR}/include) 37 | 38 | blt_add_test( 39 | NAME managed_ptr_test 40 | COMMAND managed_ptr_tests) 41 | endif () 42 | 43 | if (CHAI_ENABLE_RAJA_PLUGIN) 44 | set(raja_test_depends 45 | ${chai_integration_test_depends} 46 | RAJA) 47 | 48 | blt_add_executable( 49 | NAME raja-chai-tests 50 | SOURCES raja-chai-tests.cpp 51 | DEPENDS_ON ${raja_test_depends}) 52 | 53 | blt_add_test( 54 | NAME raja-chai-tests 55 | COMMAND raja-chai-tests) 56 | 57 | target_include_directories( 58 | raja-chai-tests 59 | PUBLIC ${PROJECT_BINARY_DIR}/include) 60 | 61 | if (CHAI_ENABLE_RAJA_NESTED_TEST) 62 | #raja kernel tests 63 | blt_add_executable( 64 | NAME raja-chai-nested-tests 65 | SOURCES raja-chai-nested.cpp 66 | DEPENDS_ON ${raja_test_depends}) 67 | 68 | blt_add_test( 69 | NAME raja-chai-nested-tests 70 | COMMAND raja-chai-nested-tests) 71 | 72 | target_include_directories( 73 | raja-chai-nested-tests 74 | PUBLIC ${PROJECT_BINARY_DIR}/include) 75 | 76 | #raja launch tests 77 | blt_add_executable( 78 | NAME raja-chai-launch-tests 79 | SOURCES raja-chai-launch.cpp 80 | DEPENDS_ON ${raja_test_depends}) 81 | 82 | blt_add_test( 83 | NAME raja-chai-launch-tests 84 | COMMAND raja-chai-launch-tests) 85 | 86 | target_include_directories( 87 | raja-chai-launch-tests 88 | PUBLIC ${PROJECT_BINARY_DIR}/include) 89 | 90 | endif () 91 | 92 | endif () 93 | -------------------------------------------------------------------------------- /tests/integration/raja-chai-tests.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | /// 8 | /// Source file containing tests for CHAI with basic RAJA constructs 9 | /// 10 | #include "RAJA/RAJA.hpp" 11 | 12 | #include "chai/ManagedArray.hpp" 13 | #include "chai/ManagedArrayView.hpp" 14 | 15 | #include 16 | 17 | #include "gtest/gtest.h" 18 | 19 | // TODO: add hip policy for these tests. 20 | #define CUDA_TEST(X, Y) \ 21 | static void cuda_test_##X##_##Y(); \ 22 | TEST(X, Y) { cuda_test_##X##_##Y(); } \ 23 | static void cuda_test_##X##_##Y() 24 | 25 | #if defined(RAJA_ENABLE_CUDA) 26 | #define PARALLEL_RAJA_DEVICE __device__ 27 | using parallel_raja_policy = RAJA::cuda_exec<16>; 28 | #elif defined(RAJA_ENABLE_OPENMP) 29 | #define PARALLEL_RAJA_DEVICE 30 | using parallel_raja_policy = RAJA::omp_parallel_for_exec; 31 | #else 32 | #define PARALLEL_RAJA_DEVICE 33 | using parallel_raja_policy = RAJA::seq_exec; 34 | #endif 35 | 36 | CUDA_TEST(ChaiTest, Simple) 37 | { 38 | chai::ManagedArray v1(10); 39 | chai::ManagedArray v2(10); 40 | 41 | RAJA::forall(RAJA::RangeSegment(0, 10), [=](int i) { 42 | v1[i] = static_cast(i * 1.0f); 43 | }); 44 | 45 | std::cout << "end of loop 1" << std::endl; 46 | 47 | RAJA::forall(RAJA::RangeSegment(0, 10), [=] PARALLEL_RAJA_DEVICE(int i) { 48 | v2[i] = v1[i] * 2.0f; 49 | }); 50 | 51 | std::cout << "end of loop 2" << std::endl; 52 | 53 | RAJA::forall(RAJA::RangeSegment(0, 10), [=](int i) { 54 | ASSERT_FLOAT_EQ(v2[i], i * 2.0f); 55 | }); 56 | 57 | RAJA::forall(RAJA::RangeSegment(0, 10), [=] PARALLEL_RAJA_DEVICE(int i) { 58 | v2[i] *= 2.0f; 59 | }); 60 | 61 | float* raw_v2 = v2.data(); 62 | for (int i = 0; i < 10; i++) { 63 | ASSERT_FLOAT_EQ(raw_v2[i], i * 2.0f * 2.0f); 64 | ; 65 | } 66 | 67 | v1.free(); 68 | v2.free(); 69 | } 70 | 71 | CUDA_TEST(ChaiTest, Views) 72 | { 73 | chai::ManagedArray v1_array(10); 74 | chai::ManagedArray v2_array(10); 75 | 76 | using view = chai::ManagedArrayView >; 77 | 78 | view v1(v1_array, 10); 79 | view v2(v2_array, 10); 80 | 81 | RAJA::forall(RAJA::RangeSegment(0, 10), [=](int i) { 82 | v1(i) = static_cast(i * 1.0f); 83 | }); 84 | 85 | RAJA::forall(RAJA::RangeSegment(0, 10), [=] PARALLEL_RAJA_DEVICE(int i) { 86 | v2(i) = v1(i) * 2.0f; 87 | }); 88 | 89 | RAJA::forall(RAJA::RangeSegment(0, 10), [=](int i) { 90 | ASSERT_FLOAT_EQ(v2(i), i * 2.0f); 91 | }); 92 | 93 | RAJA::forall(RAJA::RangeSegment(0, 10), [=] PARALLEL_RAJA_DEVICE(int i) { 94 | v2(i) *= 2.0f; 95 | }); 96 | 97 | float* raw_v2 = v2_array.data(); 98 | for (int i = 0; i < 10; i++) { 99 | ASSERT_FLOAT_EQ(raw_v2[i], i * 1.0f * 2.0f * 2.0f); 100 | ; 101 | } 102 | 103 | v1_array.free(); 104 | v2_array.free(); 105 | } 106 | 107 | #if defined(CHAI_ENABLE_MULTIVIEW_TEST) 108 | CUDA_TEST(ChaiTest, MultiView) 109 | { 110 | chai::ManagedArray v1_array(10); 111 | chai::ManagedArray v2_array(10); 112 | 113 | // TODO: This stack array gets converted to a raw host pointer, which appears 114 | // to be dereferenced on the device when accessing the multiview. 115 | chai::ManagedArray all_arrays[2]; 116 | all_arrays[0] = v1_array; 117 | all_arrays[1] = v2_array; 118 | 119 | // default MultiView 120 | using view = chai::ManagedArrayMultiView>; 121 | view mview(all_arrays, RAJA::Layout<1>(10)); 122 | 123 | // MultiView with index in 1st position 124 | using view1p = chai::ManagedArrayMultiView, 1>; 125 | view1p mview1p(all_arrays, RAJA::Layout<1>(10)); 126 | 127 | RAJA::forall(RAJA::RangeSegment(0, 10), [=](int i) { 128 | mview(0,i) = static_cast(i * 1.0f); 129 | }); 130 | 131 | RAJA::forall(RAJA::RangeSegment(0, 10), [=] PARALLEL_RAJA_DEVICE(int i) { 132 | // use both MultiViews 133 | mview(1,i) = mview1p(i,0) * 2.0f; 134 | }); 135 | 136 | RAJA::forall(RAJA::RangeSegment(0, 10), [=](int i) { 137 | ASSERT_FLOAT_EQ(mview(1,i), i * 2.0f); 138 | }); 139 | 140 | RAJA::forall(RAJA::RangeSegment(0, 10), [=] PARALLEL_RAJA_DEVICE(int i) { 141 | mview(1,i) *= 2.0f; 142 | }); 143 | 144 | // accessing pointer to v2_array 145 | float* raw_v2 = mview.data[1].data(); 146 | for (int i = 0; i < 10; i++) { 147 | ASSERT_FLOAT_EQ(raw_v2[i], i * 1.0f * 2.0f * 2.0f); 148 | ; 149 | } 150 | 151 | v1_array.free(); 152 | v2_array.free(); 153 | } 154 | #endif // defined(CHAI_ENABLE_MULTIVIEW_TEST) 155 | -------------------------------------------------------------------------------- /tests/unit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | # project contributors. See the CHAI LICENSE file for details. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | ############################################################################## 7 | set (chai_unit_test_depends 8 | chai umpire gtest) 9 | 10 | blt_list_append(TO chai_unit_test_depends ELEMENTS cuda IF ${CHAI_ENABLE_CUDA}) 11 | blt_list_append(TO chai_unit_test_depends ELEMENTS blt::hip IF ${CHAI_ENABLE_HIP}) 12 | 13 | blt_add_executable( 14 | NAME managed_array_unit_tests 15 | SOURCES managed_array_unit_tests.cpp 16 | DEPENDS_ON ${chai_unit_test_depends}) 17 | 18 | target_include_directories( 19 | managed_array_unit_tests 20 | PUBLIC ${PROJECT_BINARY_DIR}/include) 21 | 22 | blt_add_test( 23 | NAME managed_array_unit_test 24 | COMMAND managed_array_unit_tests) 25 | 26 | blt_add_executable( 27 | NAME array_manager_unit_tests 28 | SOURCES array_manager_unit_tests.cpp 29 | DEPENDS_ON ${chai_unit_test_depends}) 30 | 31 | target_include_directories( 32 | array_manager_unit_tests 33 | PUBLIC ${PROJECT_BINARY_DIR}/include) 34 | 35 | blt_add_test( 36 | NAME array_manager_unit_test 37 | COMMAND array_manager_unit_tests) 38 | 39 | if (CHAI_ENABLE_MANAGED_PTR) 40 | blt_add_executable( 41 | NAME managed_ptr_unit_tests 42 | SOURCES managed_ptr_unit_tests.cpp 43 | DEPENDS_ON ${chai_unit_test_depends}) 44 | 45 | target_include_directories( 46 | managed_ptr_unit_tests 47 | PUBLIC ${PROJECT_BINARY_DIR}/include) 48 | 49 | blt_add_test( 50 | NAME managed_ptr_unit_test 51 | COMMAND managed_ptr_unit_tests) 52 | endif () 53 | -------------------------------------------------------------------------------- /tests/unit/array_manager_unit_tests.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "gtest/gtest.h" 8 | 9 | #include "chai/ArrayManager.hpp" 10 | #include "chai/ManagedArray.hpp" 11 | #include "chai/PointerRecord.hpp" 12 | 13 | TEST(ArrayManager, Constructor) 14 | { 15 | chai::ArrayManager* rm = chai::ArrayManager::getInstance(); 16 | ASSERT_NE(rm, nullptr); 17 | } 18 | 19 | #ifndef CHAI_DISABLE_RM 20 | 21 | TEST(ArrayManager, getPointerMap) 22 | { 23 | chai::ArrayManager* rm = chai::ArrayManager::getInstance(); 24 | 25 | // Allocate one array 26 | size_t sizeOfArray1 = 5; 27 | chai::ManagedArray array1 = 28 | chai::ManagedArray(sizeOfArray1, chai::CPU); 29 | 30 | // Check map of pointers 31 | std::unordered_map map1 = 32 | rm->getPointerMap(); 33 | ASSERT_EQ(map1.size(), 1); 34 | 35 | // Check some of the entries in the pointer record 36 | ASSERT_TRUE(map1.find(array1.data()) != map1.end()); 37 | const chai::PointerRecord* record1Temp = map1[array1.data()]; 38 | ASSERT_EQ(record1Temp->m_size, sizeOfArray1 * sizeof(int)); 39 | ASSERT_EQ(record1Temp->m_last_space, chai::CPU); 40 | 41 | // Check total num arrays and total allocated memory 42 | ASSERT_EQ(rm->getTotalNumArrays(), 1); 43 | ASSERT_EQ(rm->getTotalSize(), sizeOfArray1 * sizeof(int)); 44 | 45 | // Allocate another array 46 | size_t sizeOfArray2 = 4; 47 | chai::ManagedArray array2 = 48 | chai::ManagedArray(sizeOfArray2, chai::CPU); 49 | 50 | // Check map of pointers 51 | std::unordered_map map2 = 52 | rm->getPointerMap(); 53 | ASSERT_EQ(map2.size(), 2); 54 | 55 | // Check that the entries in the first record are not changed 56 | ASSERT_TRUE(map2.find(array1.data()) != map2.end()); 57 | const chai::PointerRecord* record1 = map1[array1.data()]; 58 | ASSERT_EQ(record1->m_size, sizeOfArray1 * sizeof(int)); 59 | ASSERT_EQ(record1->m_last_space, chai::CPU); 60 | 61 | // Check some of the entries in the pointer record 62 | ASSERT_TRUE(map2.find(array2.data()) != map2.end()); 63 | const chai::PointerRecord* record2 = map2[array2.data()]; 64 | ASSERT_EQ(record2->m_size, sizeOfArray2 * sizeof(double)); 65 | ASSERT_EQ(record2->m_last_space, chai::CPU); 66 | 67 | // Check the equality of the records 68 | ASSERT_EQ(record1, record1Temp); 69 | ASSERT_NE(record1, record2); 70 | 71 | // Check total num arrays and total allocated memory 72 | ASSERT_EQ(rm->getTotalNumArrays(), 2); 73 | ASSERT_EQ(rm->getTotalSize(), 74 | (sizeOfArray1 * sizeof(int)) + (sizeOfArray2 * sizeof(double))); 75 | 76 | array1.free(); 77 | array2.free(); 78 | } 79 | 80 | /*! 81 | * \brief Tests to see if callbacks can be turned on or off 82 | */ 83 | TEST(ArrayManager, controlCallbacks) 84 | { 85 | // First check that callbacks are turned on by default 86 | chai::ArrayManager* arrayManager = chai::ArrayManager::getInstance(); 87 | 88 | // Variable for testing if callbacks are on or off 89 | bool callbacksAreOn = false; 90 | 91 | // Allocate one array and set a callback 92 | size_t sizeOfArray = 5; 93 | chai::ManagedArray array1(sizeOfArray, chai::CPU); 94 | array1.setUserCallback([&] (const chai::PointerRecord*, chai::Action, chai::ExecutionSpace) { 95 | callbacksAreOn = true; 96 | }); 97 | 98 | // Make sure the callback is called with ACTION_FREE 99 | array1.free(); 100 | ASSERT_TRUE(callbacksAreOn); 101 | 102 | // Now turn off callbacks 103 | arrayManager->disableCallbacks(); 104 | 105 | // Reset the variable for testing if callbacks are on or off 106 | callbacksAreOn = false; 107 | 108 | // Allocate another array and set a callback 109 | chai::ManagedArray array2(sizeOfArray, chai::CPU); 110 | array2.setUserCallback([&] (const chai::PointerRecord*, chai::Action, chai::ExecutionSpace) { 111 | callbacksAreOn = true; 112 | }); 113 | 114 | // Make sure the callback is called with ACTION_FREE 115 | array2.free(); 116 | ASSERT_FALSE(callbacksAreOn); 117 | 118 | // Now make sure the order doesn't matter for when the callback is set compared 119 | // to when callbacks are enabled 120 | 121 | // Reset the variable for testing if callbacks are on or off 122 | callbacksAreOn = false; 123 | 124 | // Allocate a third array and set a callback 125 | chai::ManagedArray array3(sizeOfArray, chai::CPU); 126 | array3.setUserCallback([&] (const chai::PointerRecord*, chai::Action, chai::ExecutionSpace) { 127 | callbacksAreOn = true; 128 | }); 129 | 130 | // Turn on callbacks 131 | arrayManager->enableCallbacks(); 132 | 133 | // Make sure the callback is called with ACTION_FREE 134 | array3.free(); 135 | ASSERT_TRUE(callbacksAreOn); 136 | } 137 | 138 | /*! 139 | * \brief Tests to see if global callback can be turned on or off 140 | */ 141 | TEST(ArrayManager, controlGlobalCallback) 142 | { 143 | // First check that callbacks are turned on by default 144 | chai::ArrayManager* arrayManager = chai::ArrayManager::getInstance(); 145 | 146 | // Variable for testing if callbacks are on or off 147 | bool callbacksAreOn = false; 148 | 149 | // Set a global callback 150 | arrayManager->setGlobalUserCallback([&] (const chai::PointerRecord*, chai::Action, chai::ExecutionSpace) { 151 | callbacksAreOn = true; 152 | }); 153 | 154 | // Allocate an array and make sure the callback was called 155 | size_t sizeOfArray = 5; 156 | chai::ManagedArray array(sizeOfArray, chai::CPU); 157 | ASSERT_TRUE(callbacksAreOn); 158 | 159 | // Now turn off callbacks 160 | arrayManager->disableCallbacks(); 161 | 162 | // Reset the variable for testing if callbacks are on or off 163 | callbacksAreOn = false; 164 | 165 | // Realloc the array and make sure the callback was NOT called 166 | array.reallocate(2 * sizeOfArray); 167 | ASSERT_FALSE(callbacksAreOn); 168 | 169 | // Now make sure the order doesn't matter for when the callback is set compared 170 | // to when callbacks are enabled 171 | arrayManager->setGlobalUserCallback([&] (const chai::PointerRecord*, chai::Action, chai::ExecutionSpace) { 172 | callbacksAreOn = true; 173 | }); 174 | 175 | // Reset the variable for testing if callbacks are on or off 176 | callbacksAreOn = false; 177 | 178 | // Turn on callbacks 179 | arrayManager->enableCallbacks(); 180 | 181 | // Make sure the callback is called 182 | array.free(); 183 | ASSERT_TRUE(callbacksAreOn); 184 | } 185 | 186 | #endif // !CHAI_DISABLE_RM 187 | -------------------------------------------------------------------------------- /tests/unit/managed_array_unit_tests.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC and CHAI 3 | // project contributors. See the CHAI LICENSE file for details. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | ////////////////////////////////////////////////////////////////////////////// 7 | #include "gtest/gtest.h" 8 | 9 | #define GPU_TEST(X, Y) \ 10 | static void gpu_test_##X##Y(); \ 11 | TEST(X, Y) { gpu_test_##X##Y(); } \ 12 | static void gpu_test_##X##Y() 13 | 14 | #include "chai/config.hpp" 15 | 16 | #include "chai/ManagedArray.hpp" 17 | 18 | TEST(ManagedArray, DefaultConstructor) 19 | { 20 | chai::ManagedArray array; 21 | ASSERT_EQ(array.size(), 0u); 22 | } 23 | 24 | TEST(ManagedArray, SizeConstructor) 25 | { 26 | chai::ManagedArray array(10); 27 | ASSERT_EQ(array.size(), 10u); 28 | array.free(); 29 | } 30 | 31 | TEST(ManagedArray, SpaceConstructorCPU) 32 | { 33 | chai::ManagedArray array(10, chai::CPU); 34 | ASSERT_EQ(array.size(), 10u); 35 | array.free(); 36 | } 37 | 38 | #if defined(CHAI_ENABLE_CUDA) || defined(CHAI_ENABLE_HIP) 39 | TEST(ManagedArray, SpaceConstructorGPU) 40 | { 41 | chai::ManagedArray array(10, chai::GPU); 42 | ASSERT_EQ(array.size(), 10u); 43 | array.free(); 44 | } 45 | 46 | #if defined(CHAI_ENABLE_UM) 47 | TEST(ManagedArray, SpaceConstructorUM) 48 | { 49 | chai::ManagedArray array(10, chai::UM); 50 | ASSERT_EQ(array.size(), 10u); 51 | array.free(); 52 | } 53 | #endif 54 | #endif 55 | --------------------------------------------------------------------------------