Update Kokkos library in LAMMPS to v3.6.0
This commit is contained in:
@ -119,8 +119,8 @@ Device backends can be enabled by specifying `-DKokkos_ENABLE_X`.
|
|||||||
* Kokkos_ENABLE_OPENMP
|
* Kokkos_ENABLE_OPENMP
|
||||||
* Whether to build OpenMP backend
|
* Whether to build OpenMP backend
|
||||||
* BOOL Default: OFF
|
* BOOL Default: OFF
|
||||||
* Kokkos_ENABLE_PTHREAD
|
* Kokkos_ENABLE_THREADS
|
||||||
* Whether to build Pthread backend
|
* Whether to build C++ thread backend
|
||||||
* BOOL Default: OFF
|
* BOOL Default: OFF
|
||||||
* Kokkos_ENABLE_SERIAL
|
* Kokkos_ENABLE_SERIAL
|
||||||
* Whether to build serial backend
|
* Whether to build serial backend
|
||||||
@ -178,7 +178,7 @@ Options can be enabled by specifying `-DKokkos_ENABLE_X`.
|
|||||||
* Whether to print information about which profiling tools gotloaded
|
* Whether to print information about which profiling tools gotloaded
|
||||||
* BOOL Default: OFF
|
* BOOL Default: OFF
|
||||||
* Kokkos_ENABLE_TESTS
|
* Kokkos_ENABLE_TESTS
|
||||||
* Whether to build serial backend
|
* Whether to enable test suite
|
||||||
* BOOL Default: OFF
|
* BOOL Default: OFF
|
||||||
|
|
||||||
## Other Options
|
## Other Options
|
||||||
|
|||||||
@ -1,5 +1,120 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## [3.6.00](https://github.com/kokkos/kokkos/tree/3.6.00) (2022-02-18)
|
||||||
|
[Full Changelog](https://github.com/kokkos/kokkos/compare/3.5.00...3.6.00)
|
||||||
|
|
||||||
|
### Features:
|
||||||
|
- Add C++ standard algorithms [\#4315](https://github.com/kokkos/kokkos/pull/4315)
|
||||||
|
- Implement `fill_random` for `DynRankView` [\#4763](https://github.com/kokkos/kokkos/pull/4763)
|
||||||
|
- Add `bhalf_t` [\#4543](https://github.com/kokkos/kokkos/pull/4543) [\#4653](https://github.com/kokkos/kokkos/pull/4653)
|
||||||
|
- Add mathematical constants [\#4519](https://github.com/kokkos/kokkos/pull/4519)
|
||||||
|
- Allow `Kokkos::{create_mirror*,resize,realloc}` to be used with `WithoutInitializing` [\#4486](https://github.com/kokkos/kokkos/pull/4486) [\#4337](https://github.com/kokkos/kokkos/pull/4337)
|
||||||
|
- Implement `KOKKOS_IF_ON_{HOST,DEVICE}` macros [\#4660](https://github.com/kokkos/kokkos/pull/4660)
|
||||||
|
- Allow setting the CMake language for Kokkos [\#4323](https://github.com/kokkos/kokkos/pull/4323)
|
||||||
|
|
||||||
|
#### Perf bug fix
|
||||||
|
- Desul: Add ScopeCaller [\#4690](https://github.com/kokkos/kokkos/pull/4690)
|
||||||
|
- Enable Desul atomics by default when using Makefiles [\#4606](https://github.com/kokkos/kokkos/pull/4606)
|
||||||
|
- Unique token improvement [\#4741](https://github.com/kokkos/kokkos/pull/4741) [\#4748](https://github.com/kokkos/kokkos/pull/4748)
|
||||||
|
|
||||||
|
#### Other improvements:
|
||||||
|
- Add math function long double overload on the host side [\#4712](https://github.com/kokkos/kokkos/pull/4712)
|
||||||
|
|
||||||
|
### Deprecations:
|
||||||
|
- Array reductions with pointer return types [\#4756](https://github.com/kokkos/kokkos/pull/4756)
|
||||||
|
- Deprecate `partition_master`, `validate_partition` [\#4737](https://github.com/kokkos/kokkos/pull/4737)
|
||||||
|
- Deprecate `Kokkos_ENABLE_PTHREAD` in favor of `Kokkos_ENABLE_THREADS` [\#4619](https://github.com/kokkos/kokkos/pull/4619) ** pair with use std::threads **
|
||||||
|
- Deprecate `log2(unsigned) -> int` (removing in next release) [\#4595](https://github.com/kokkos/kokkos/pull/4595)
|
||||||
|
- Deprecate `Kokkos::Impl::is_view` [\#4592](https://github.com/kokkos/kokkos/pull/4592)
|
||||||
|
- Deprecate `KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_*` macros and the `ActiveExecutionMemorySpace` alias [\#4668](https://github.com/kokkos/kokkos/issues/4668)
|
||||||
|
|
||||||
|
### Backends and Archs Enhancements:
|
||||||
|
|
||||||
|
#### SYCL:
|
||||||
|
- Update required SYCL compiler version [\#4749](https://github.com/kokkos/kokkos/pull/4749)
|
||||||
|
- Cap vector size to kernel maximum for SYCL [\#4704](https://github.com/kokkos/kokkos/pull/4704)
|
||||||
|
- Improve check for compatibility of vector size and subgroup size in SYCL [\#4579](https://github.com/kokkos/kokkos/pull/4579)
|
||||||
|
- Provide `chunk_size` for SYCL [\#4635](https://github.com/kokkos/kokkos/pull/4635)
|
||||||
|
- Use host-pinned memory for SYCL kernel memory [\#4627](https://github.com/kokkos/kokkos/pull/4627)
|
||||||
|
- Use shuffle-based algorithm for scalar reduction [\#4608](https://github.com/kokkos/kokkos/pull/4608)
|
||||||
|
- Implement pool of USM IndirectKernelMemory [\#4596](https://github.com/kokkos/kokkos/pull/4596)
|
||||||
|
- Provide valid default team size for SYCL [\#4481](https://github.com/kokkos/kokkos/pull/4481)
|
||||||
|
|
||||||
|
#### CUDA:
|
||||||
|
- Add checks for shmem usage in `parallel_reduce` [\#4548](https://github.com/kokkos/kokkos/pull/4548)
|
||||||
|
|
||||||
|
#### HIP:
|
||||||
|
- Add support for fp16 in the HIP backend [\#4688](https://github.com/kokkos/kokkos/pull/4688)
|
||||||
|
- Disable multiple kernel instantiations when using HIP (configure with `-DKokkos_ENABLE_HIP_MULTIPLE_KERNEL_INSTANTIATIONS=ON` to use) [\#4644](https://github.com/kokkos/kokkos/pull/4644)
|
||||||
|
- Fix HIP scratch use per instance [\#4439](https://github.com/kokkos/kokkos/pull/4439)
|
||||||
|
- Change allocation header to 256B alignment for AMD VEGA architecture [\#4753](https://github.com/kokkos/kokkos/pull/4753)
|
||||||
|
- Add generic `KOKKOS_ARCH_VEGA` macro [\#4782](https://github.com/kokkos/kokkos/pull/4782)
|
||||||
|
- Require ROCm 4.5 [\#4689](https://github.com/kokkos/kokkos/pull/4689)
|
||||||
|
|
||||||
|
### HPX:
|
||||||
|
- Adapt to HPX 1.7.0 which is now required [\#4241](https://github.com/kokkos/kokkos/pull/4241)
|
||||||
|
|
||||||
|
#### OpenMP:
|
||||||
|
- Fix thread deduction for OpenMP for `thread_count==0` [\#4541](https://github.com/kokkos/kokkos/pull/4541)
|
||||||
|
|
||||||
|
#### OpenMPTarget:
|
||||||
|
- Update memory space `size_type` to improve performance (`size_t -> unsigned`) [\#4779](https://github.com/kokkos/kokkos/pull/4779)
|
||||||
|
|
||||||
|
#### Other Improvements:
|
||||||
|
- Improve NVHPC support [\#4599](https://github.com/kokkos/kokkos/pull/4599)
|
||||||
|
- Add `Kokkos::Experimental::{min,max,minmax,clamp}` [\#4629](https://github.com/kokkos/kokkos/pull/4629) [\#4506](https://github.com/kokkos/kokkos/pull/4506)
|
||||||
|
- Use device type as template argument in Containers and Algorithms [\#4724](https://github.com/kokkos/kokkos/pull/4724) [\#4675](https://github.com/kokkos/kokkos/pull/4675)
|
||||||
|
- Implement `Kokkos::sort` with execution space [\#4490](https://github.com/kokkos/kokkos/pull/4490)
|
||||||
|
- `Kokkos::resize` always error out for mismatch in runtime rank [\#4681](https://github.com/kokkos/kokkos/pull/4681)
|
||||||
|
- Print current call stack when calling `Kokkos::abort()` from the host [\#4672](https://github.com/kokkos/kokkos/pull/4672) [\#4671](https://github.com/kokkos/kokkos/pull/4671)
|
||||||
|
- Detect mismatch of execution spaces in functors [\#4655](https://github.com/kokkos/kokkos/pull/4655)
|
||||||
|
- Improve view label access on host [\#4647](https://github.com/kokkos/kokkos/pull/4647)
|
||||||
|
- Error out for `const` scalar return type in reduction [\#4645](https://github.com/kokkos/kokkos/pull/4645)
|
||||||
|
- Don't allow calling `UnorderdMap::value_at` for a set [\#4639](https://github.com/kokkos/kokkos/pull/4639)
|
||||||
|
- Add `KOKKOS_COMPILER_NVHPC` macro, disable `quiet_NaN` and `signaling_NaN` [\#4586](https://github.com/kokkos/kokkos/pull/4586)
|
||||||
|
- Improve performance of `local_deep_copy` [\#4511](https://github.com/kokkos/kokkos/pull/4511)
|
||||||
|
- Improve performance when sorting integers [\#4464](https://github.com/kokkos/kokkos/pull/4464)
|
||||||
|
- Add missing numeric traits (`denorm_min`, `reciprocal_overflow_threshold`, `{quiet,silent}_NaN}`) and make them work on cv-qualified types [\#4466](https://github.com/kokkos/kokkos/pull/4466) [\#4415](https://github.com/kokkos/kokkos/pull/4415) [\#4473](https://github.com/kokkos/kokkos/pull/4473) [\#4443](https://github.com/kokkos/kokkos/pull/4443)
|
||||||
|
|
||||||
|
### Implemented enhancements BuildSystem
|
||||||
|
- Manually compute IntelLLVM compiler version for older CMake versions [\#4760](https://github.com/kokkos/kokkos/pull/4760)
|
||||||
|
- Add Xptxas without = to `nvcc_wrapper` [\#4646](https://github.com/kokkos/kokkos/pull/4646)
|
||||||
|
- Use external GoogleTest optionally [\#4563](https://github.com/kokkos/kokkos/pull/4563)
|
||||||
|
- Silent warnings about multiple optimization flags with `nvcc_wrapper` [\#4502](https://github.com/kokkos/kokkos/pull/4502)
|
||||||
|
- Use the same flags in Makefile.kokkos for POWER7/8/9 as for CMake [\#4483](https://github.com/kokkos/kokkos/pull/4483)
|
||||||
|
- Fix support for A64FX architecture [\#4745](https://github.com/kokkos/kokkos/pull/4745)
|
||||||
|
|
||||||
|
### Incompatibilities:
|
||||||
|
- Drop `KOKKOS_ARCH_HIP` macro when using generated GNU makefiles [\#4786](https://github.com/kokkos/kokkos/pull/4786)
|
||||||
|
- Remove gcc-toolchain auto add for clang in Makefile.kokkos [\#4762](https://github.com/kokkos/kokkos/pull/4762)
|
||||||
|
|
||||||
|
### Bug Fixes:
|
||||||
|
- Lock constant memory in Cuda/HIP kernel launch with a mutex (thread safety) [\#4525](https://github.com/kokkos/kokkos/pull/4525)
|
||||||
|
- Fix overflow for large requested scratch allocation [\#4551](https://github.com/kokkos/kokkos/pull/4551)
|
||||||
|
- Fix Windows build in mingw [\#4564](https://github.com/kokkos/kokkos/pull/4564)
|
||||||
|
- Fix `kokkos_launch_compiler`: escape `$` character [\#4769](https://github.com/kokkos/kokkos/pull/4769) [\#4703](https://github.com/kokkos/kokkos/pull/4703)
|
||||||
|
- Fix math functions with NVCC and GCC 5 as host compiler [\#4733](https://github.com/kokkos/kokkos/pull/4733)
|
||||||
|
- Fix shared build with Intel19 [\#4725](https://github.com/kokkos/kokkos/pull/4725)
|
||||||
|
- Do not install empty `desul/src/` directory [\#4714](https://github.com/kokkos/kokkos/pull/4714)
|
||||||
|
- Fix wrong `device_id` computation in `identifier_from_devid` (Profiling Interface) [\#4694](https://github.com/kokkos/kokkos/pull/4694)
|
||||||
|
- Fix a bug in CUDA scratch memory pool (abnormally high memory consumption) [\#4673](https://github.com/kokkos/kokkos/pull/4673)
|
||||||
|
- Remove eval of command args in `hpcbind` [\#4630](https://github.com/kokkos/kokkos/pull/4630)
|
||||||
|
- SYCL fix to run when no GPU is detected [\#4623](https://github.com/kokkos/kokkos/pull/4623)
|
||||||
|
- Fix `layout_strides::span` for rank-0 views [\#4605](https://github.com/kokkos/kokkos/pull/4605)
|
||||||
|
- Fix SYCL atomics for local memory [\#4585](https://github.com/kokkos/kokkos/pull/4585)
|
||||||
|
- Hotfix `mdrange_large_deep_copy` for SYCL [\#4581](https://github.com/kokkos/kokkos/pull/4581)
|
||||||
|
- Fix bug when sorting integer using the HIP backend [\#4570](https://github.com/kokkos/kokkos/pull/4570)
|
||||||
|
- Fix compilation error when using HIP with RDC [\#4553](https://github.com/kokkos/kokkos/pull/4553)
|
||||||
|
- `DynamicView`: Fix deallocation extent [\#4533](https://github.com/kokkos/kokkos/pull/4533)
|
||||||
|
- SYCL fix running parallel_reduce with TeamPolicy for large ranges [\#4532](https://github.com/kokkos/kokkos/pull/4532)
|
||||||
|
- Fix bash syntax error in `nvcc_wrapper` [\#4524](https://github.com/kokkos/kokkos/pull/4524)
|
||||||
|
- OpenMPTarget `team_policy` reduce fixes for `init/join` reductions [\#4521](https://github.com/kokkos/kokkos/pull/4521)
|
||||||
|
- Avoid hangs in the Threads backend [\#4499](https://github.com/kokkos/kokkos/pull/4499)
|
||||||
|
- OpenMPTarget fix reduction bug in `parallel_reduce` for `TeamPolicy` [\#4491](https://github.com/kokkos/kokkos/pull/4491)
|
||||||
|
- HIP fix scratch space per instance [\#4439](https://github.com/kokkos/kokkos/pull/4439)
|
||||||
|
- OpenMPTarget fix team scratch allocation [\#4431](https://github.com/kokkos/kokkos/pull/4431)
|
||||||
|
|
||||||
|
|
||||||
## [3.5.00](https://github.com/kokkos/kokkos/tree/3.5.00) (2021-10-19)
|
## [3.5.00](https://github.com/kokkos/kokkos/tree/3.5.00) (2021-10-19)
|
||||||
[Full Changelog](https://github.com/kokkos/kokkos/compare/3.4.01...3.5.00)
|
[Full Changelog](https://github.com/kokkos/kokkos/compare/3.4.01...3.5.00)
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
# Disable in-source builds to prevent source tree corruption.
|
# Disable in-source builds to prevent source tree corruption.
|
||||||
if( "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}" )
|
if( "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}" )
|
||||||
message( FATAL_ERROR "FATAL: In-source builds are not allowed. You should create a separate directory for build files." )
|
message( FATAL_ERROR "FATAL: In-source builds are not allowed. You should create a separate directory for build files and delete CMakeCache.txt." )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# We want to determine if options are given with the wrong case
|
# We want to determine if options are given with the wrong case
|
||||||
@ -75,7 +75,31 @@ IF(NOT KOKKOS_HAS_TRILINOS)
|
|||||||
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
|
||||||
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
|
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
|
||||||
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
|
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
|
||||||
|
|
||||||
|
# What language are we compiling Kokkos as
|
||||||
|
# downstream dependencies need to match this!
|
||||||
|
SET(KOKKOS_COMPILE_LANGUAGE CXX)
|
||||||
|
# use lower case here since we didn't parse options yet
|
||||||
|
IF (Kokkos_ENABLE_COMPILE_AS_CMAKE_LANGUAGE)
|
||||||
|
|
||||||
|
# Without this as a language for the package we would get a C++ compiler enabled.
|
||||||
|
# but we still need a C++ compiler even if we build all our cpp files as CUDA only
|
||||||
|
# because otherwise the C++ features don't work etc.
|
||||||
|
# This is just the rather odd way CMake does this, since CUDA doesn't imply C++ even
|
||||||
|
# though it is a C++ extension ... (but I guess it didn't use to be back in CUDA 4 or 5
|
||||||
|
# days.
|
||||||
|
SET(KOKKOS_INTERNAL_EXTRA_COMPILE_LANGUAGE CXX)
|
||||||
|
|
||||||
|
IF (Kokkos_ENABLE_CUDA)
|
||||||
|
SET(KOKKOS_COMPILE_LANGUAGE CUDA)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
IF (Spack_WORKAROUND)
|
IF (Spack_WORKAROUND)
|
||||||
|
IF (Kokkos_ENABLE_COMPILE_AS_CMAKE_LANGUAGE)
|
||||||
|
MESSAGE(FATAL_ERROR "Can't currently use Kokkos_ENABLE_COMPILER_AS_CMAKE_LANGUAGE in a spack installation!")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
#if we are explicitly using Spack for development,
|
#if we are explicitly using Spack for development,
|
||||||
#nuke the Spack compiler
|
#nuke the Spack compiler
|
||||||
SET(SPACK_CXX $ENV{SPACK_CXX})
|
SET(SPACK_CXX $ENV{SPACK_CXX})
|
||||||
@ -86,7 +110,7 @@ IF(NOT KOKKOS_HAS_TRILINOS)
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
# Always call the project command to define Kokkos_ variables
|
# Always call the project command to define Kokkos_ variables
|
||||||
# and to make sure that C++ is an enabled language
|
# and to make sure that C++ is an enabled language
|
||||||
PROJECT(Kokkos CXX)
|
PROJECT(Kokkos ${KOKKOS_COMPILE_LANGUAGE} ${KOKKOS_INTERNAL_EXTRA_COMPILE_LANGUAGE})
|
||||||
IF(NOT HAS_PARENT)
|
IF(NOT HAS_PARENT)
|
||||||
IF (NOT CMAKE_BUILD_TYPE)
|
IF (NOT CMAKE_BUILD_TYPE)
|
||||||
SET(DEFAULT_BUILD_TYPE "RelWithDebInfo")
|
SET(DEFAULT_BUILD_TYPE "RelWithDebInfo")
|
||||||
@ -111,7 +135,7 @@ ENDIF()
|
|||||||
|
|
||||||
|
|
||||||
set(Kokkos_VERSION_MAJOR 3)
|
set(Kokkos_VERSION_MAJOR 3)
|
||||||
set(Kokkos_VERSION_MINOR 5)
|
set(Kokkos_VERSION_MINOR 6)
|
||||||
set(Kokkos_VERSION_PATCH 00)
|
set(Kokkos_VERSION_PATCH 00)
|
||||||
set(Kokkos_VERSION "${Kokkos_VERSION_MAJOR}.${Kokkos_VERSION_MINOR}.${Kokkos_VERSION_PATCH}")
|
set(Kokkos_VERSION "${Kokkos_VERSION_MAJOR}.${Kokkos_VERSION_MINOR}.${Kokkos_VERSION_PATCH}")
|
||||||
math(EXPR KOKKOS_VERSION "${Kokkos_VERSION_MAJOR} * 10000 + ${Kokkos_VERSION_MINOR} * 100 + ${Kokkos_VERSION_PATCH}")
|
math(EXPR KOKKOS_VERSION "${Kokkos_VERSION_MAJOR} * 10000 + ${Kokkos_VERSION_MINOR} * 100 + ${Kokkos_VERSION_PATCH}")
|
||||||
@ -151,6 +175,10 @@ IF(NOT MSVC)
|
|||||||
GLOBAL_APPEND(KOKKOS_LINK_OPTIONS -DKOKKOS_DEPENDENCE)
|
GLOBAL_APPEND(KOKKOS_LINK_OPTIONS -DKOKKOS_DEPENDENCE)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF(Kokkos_ENABLE_TESTS AND NOT KOKKOS_HAS_TRILINOS)
|
||||||
|
find_package(GTest)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
# Include a set of Kokkos-specific wrapper functions that
|
# Include a set of Kokkos-specific wrapper functions that
|
||||||
# will either call raw CMake or TriBITS
|
# will either call raw CMake or TriBITS
|
||||||
# These are functions like KOKKOS_INCLUDE_DIRECTORIES
|
# These are functions like KOKKOS_INCLUDE_DIRECTORIES
|
||||||
@ -174,10 +202,6 @@ KOKKOS_SETUP_BUILD_ENVIRONMENT()
|
|||||||
# 7) Export and install targets
|
# 7) Export and install targets
|
||||||
|
|
||||||
OPTION(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
OPTION(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
||||||
# Workaround for building position independent code.
|
|
||||||
IF(BUILD_SHARED_LIBS)
|
|
||||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
SET(KOKKOS_EXT_LIBRARIES Kokkos::kokkos Kokkos::kokkoscore Kokkos::kokkoscontainers Kokkos::kokkosalgorithms)
|
SET(KOKKOS_EXT_LIBRARIES Kokkos::kokkos Kokkos::kokkoscore Kokkos::kokkoscontainers Kokkos::kokkosalgorithms)
|
||||||
SET(KOKKOS_INT_LIBRARIES kokkos kokkoscore kokkoscontainers kokkosalgorithms)
|
SET(KOKKOS_INT_LIBRARIES kokkos kokkoscore kokkoscontainers kokkosalgorithms)
|
||||||
|
|||||||
@ -11,13 +11,13 @@ CXXFLAGS += $(SHFLAGS)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
KOKKOS_VERSION_MAJOR = 3
|
KOKKOS_VERSION_MAJOR = 3
|
||||||
KOKKOS_VERSION_MINOR = 5
|
KOKKOS_VERSION_MINOR = 6
|
||||||
KOKKOS_VERSION_PATCH = 00
|
KOKKOS_VERSION_PATCH = 00
|
||||||
KOKKOS_VERSION = $(shell echo $(KOKKOS_VERSION_MAJOR)*10000+$(KOKKOS_VERSION_MINOR)*100+$(KOKKOS_VERSION_PATCH) | bc)
|
KOKKOS_VERSION = $(shell echo $(KOKKOS_VERSION_MAJOR)*10000+$(KOKKOS_VERSION_MINOR)*100+$(KOKKOS_VERSION_PATCH) | bc)
|
||||||
|
|
||||||
# Options: Cuda,HIP,SYCL,OpenMPTarget,OpenMP,Pthread,Serial
|
# Options: Cuda,HIP,SYCL,OpenMPTarget,OpenMP,Threads,Serial
|
||||||
KOKKOS_DEVICES ?= "OpenMP"
|
KOKKOS_DEVICES ?= "OpenMP"
|
||||||
#KOKKOS_DEVICES ?= "Pthread"
|
#KOKKOS_DEVICES ?= "Threads"
|
||||||
# Options:
|
# Options:
|
||||||
# Intel: KNC,KNL,SNB,HSW,BDW,SKX
|
# Intel: KNC,KNL,SNB,HSW,BDW,SKX
|
||||||
# NVIDIA: Kepler,Kepler30,Kepler32,Kepler35,Kepler37,Maxwell,Maxwell50,Maxwell52,Maxwell53,Pascal60,Pascal61,Volta70,Volta72,Turing75,Ampere80,Ampere86
|
# NVIDIA: Kepler,Kepler30,Kepler32,Kepler35,Kepler37,Maxwell,Maxwell50,Maxwell52,Maxwell53,Pascal60,Pascal61,Volta70,Volta72,Turing75,Ampere80,Ampere86
|
||||||
@ -33,8 +33,8 @@ KOKKOS_DEBUG ?= "no"
|
|||||||
KOKKOS_USE_TPLS ?= ""
|
KOKKOS_USE_TPLS ?= ""
|
||||||
# Options: c++14,c++1y,c++17,c++1z,c++2a
|
# Options: c++14,c++1y,c++17,c++1z,c++2a
|
||||||
KOKKOS_CXX_STANDARD ?= "c++14"
|
KOKKOS_CXX_STANDARD ?= "c++14"
|
||||||
# Options: aggressive_vectorization,disable_profiling,enable_large_mem_tests,disable_complex_align,disable_deprecated_code,enable_deprecation_warnings,enable_desul_atomics
|
# Options: aggressive_vectorization,disable_profiling,enable_large_mem_tests,disable_complex_align,disable_deprecated_code,enable_deprecation_warnings,disable_desul_atomics
|
||||||
KOKKOS_OPTIONS ?= "enable_desul_atomics"
|
KOKKOS_OPTIONS ?= ""
|
||||||
KOKKOS_CMAKE ?= "no"
|
KOKKOS_CMAKE ?= "no"
|
||||||
KOKKOS_TRIBITS ?= "no"
|
KOKKOS_TRIBITS ?= "no"
|
||||||
KOKKOS_STANDALONE_CMAKE ?= "no"
|
KOKKOS_STANDALONE_CMAKE ?= "no"
|
||||||
@ -93,7 +93,9 @@ KOKKOS_INTERNAL_CUDA_USE_RELOC := $(call kokkos_has_string,$(KOKKOS_CUDA_OPTIONS
|
|||||||
KOKKOS_INTERNAL_CUDA_USE_LAMBDA := $(call kokkos_has_string,$(KOKKOS_CUDA_OPTIONS),enable_lambda)
|
KOKKOS_INTERNAL_CUDA_USE_LAMBDA := $(call kokkos_has_string,$(KOKKOS_CUDA_OPTIONS),enable_lambda)
|
||||||
KOKKOS_INTERNAL_CUDA_USE_CONSTEXPR := $(call kokkos_has_string,$(KOKKOS_CUDA_OPTIONS),enable_constexpr)
|
KOKKOS_INTERNAL_CUDA_USE_CONSTEXPR := $(call kokkos_has_string,$(KOKKOS_CUDA_OPTIONS),enable_constexpr)
|
||||||
KOKKOS_INTERNAL_HPX_ENABLE_ASYNC_DISPATCH := $(call kokkos_has_string,$(KOKKOS_HPX_OPTIONS),enable_async_dispatch)
|
KOKKOS_INTERNAL_HPX_ENABLE_ASYNC_DISPATCH := $(call kokkos_has_string,$(KOKKOS_HPX_OPTIONS),enable_async_dispatch)
|
||||||
|
# deprecated
|
||||||
KOKKOS_INTERNAL_ENABLE_DESUL_ATOMICS := $(call kokkos_has_string,$(KOKKOS_OPTIONS),enable_desul_atomics)
|
KOKKOS_INTERNAL_ENABLE_DESUL_ATOMICS := $(call kokkos_has_string,$(KOKKOS_OPTIONS),enable_desul_atomics)
|
||||||
|
KOKKOS_INTERNAL_DISABLE_DESUL_ATOMICS := $(call kokkos_has_string,$(KOKKOS_OPTIONS),disable_desul_atomics)
|
||||||
KOKKOS_INTERNAL_DISABLE_DEPRECATED_CODE := $(call kokkos_has_string,$(KOKKOS_OPTIONS),disable_deprecated_code)
|
KOKKOS_INTERNAL_DISABLE_DEPRECATED_CODE := $(call kokkos_has_string,$(KOKKOS_OPTIONS),disable_deprecated_code)
|
||||||
KOKKOS_INTERNAL_ENABLE_DEPRECATION_WARNINGS := $(call kokkos_has_string,$(KOKKOS_OPTIONS),enable_deprecation_warnings)
|
KOKKOS_INTERNAL_ENABLE_DEPRECATION_WARNINGS := $(call kokkos_has_string,$(KOKKOS_OPTIONS),enable_deprecation_warnings)
|
||||||
|
|
||||||
@ -101,12 +103,18 @@ KOKKOS_INTERNAL_HIP_USE_RELOC := $(call kokkos_has_string,$(KOKKOS_HIP_OPTIONS),
|
|||||||
|
|
||||||
# Check for Kokkos Host Execution Spaces one of which must be on.
|
# Check for Kokkos Host Execution Spaces one of which must be on.
|
||||||
KOKKOS_INTERNAL_USE_OPENMP := $(call kokkos_has_string,$(subst OpenMPTarget,,$(KOKKOS_DEVICES)),OpenMP)
|
KOKKOS_INTERNAL_USE_OPENMP := $(call kokkos_has_string,$(subst OpenMPTarget,,$(KOKKOS_DEVICES)),OpenMP)
|
||||||
KOKKOS_INTERNAL_USE_PTHREADS := $(call kokkos_has_string,$(KOKKOS_DEVICES),Pthread)
|
KOKKOS_INTERNAL_USE_THREADS := $(call kokkos_has_string,$(KOKKOS_DEVICES),Threads)
|
||||||
|
# deprecated
|
||||||
|
KOKKOS_INTERNAL_USE_PTHREAD := $(call kokkos_has_string,$(KOKKOS_DEVICES),Pthread)
|
||||||
KOKKOS_INTERNAL_USE_HPX := $(call kokkos_has_string,$(KOKKOS_DEVICES),HPX)
|
KOKKOS_INTERNAL_USE_HPX := $(call kokkos_has_string,$(KOKKOS_DEVICES),HPX)
|
||||||
KOKKOS_INTERNAL_USE_SERIAL := $(call kokkos_has_string,$(KOKKOS_DEVICES),Serial)
|
KOKKOS_INTERNAL_USE_SERIAL := $(call kokkos_has_string,$(KOKKOS_DEVICES),Serial)
|
||||||
|
ifeq ($(KOKKOS_INTERNAL_USE_PTHREAD), 1)
|
||||||
|
KOKKOS_INTERNAL_USE_THREADS := 1
|
||||||
|
$(warning Warning: Pthread is deprecated. Use Threads instead! KOKKOS_DEVICES=$(KOKKOS_DEVICES))
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 0)
|
ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 0)
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 0)
|
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 0)
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_HPX), 0)
|
ifeq ($(KOKKOS_INTERNAL_USE_HPX), 0)
|
||||||
KOKKOS_INTERNAL_USE_SERIAL := 1
|
KOKKOS_INTERNAL_USE_SERIAL := 1
|
||||||
endif
|
endif
|
||||||
@ -126,7 +134,7 @@ endif
|
|||||||
ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
|
||||||
KOKKOS_DEVICELIST += OpenMP
|
KOKKOS_DEVICELIST += OpenMP
|
||||||
endif
|
endif
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
|
||||||
KOKKOS_DEVICELIST += Threads
|
KOKKOS_DEVICELIST += Threads
|
||||||
endif
|
endif
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_HPX), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_HPX), 1)
|
||||||
@ -531,7 +539,7 @@ ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
|
|||||||
tmp := $(call kokkos_append_header,'$H''define KOKKOS_ENABLE_OPENMP')
|
tmp := $(call kokkos_append_header,'$H''define KOKKOS_ENABLE_OPENMP')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ENABLE_THREADS")
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ENABLE_THREADS")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -952,18 +960,8 @@ ifeq ($(KOKKOS_INTERNAL_USE_ARCH_POWER8), 1)
|
|||||||
ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1)
|
ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1)
|
||||||
|
|
||||||
else
|
else
|
||||||
ifeq ($(KOKKOS_INTERNAL_COMPILER_XL), 1)
|
|
||||||
KOKKOS_CXXFLAGS += -mcpu=power8 -mtune=power8
|
KOKKOS_CXXFLAGS += -mcpu=power8 -mtune=power8
|
||||||
KOKKOS_LDFLAGS += -mcpu=power8 -mtune=power8
|
KOKKOS_LDFLAGS += -mcpu=power8 -mtune=power8
|
||||||
else
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_COMPILER_NVCC), 1)
|
|
||||||
|
|
||||||
else
|
|
||||||
# Assume that this is a really a GNU compiler on P8.
|
|
||||||
KOKKOS_CXXFLAGS += -mcpu=power8 -mtune=power8
|
|
||||||
KOKKOS_LDFLAGS += -mcpu=power8 -mtune=power8
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -973,18 +971,8 @@ ifeq ($(KOKKOS_INTERNAL_USE_ARCH_POWER9), 1)
|
|||||||
ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1)
|
ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1)
|
||||||
|
|
||||||
else
|
else
|
||||||
ifeq ($(KOKKOS_INTERNAL_COMPILER_XL), 1)
|
|
||||||
KOKKOS_CXXFLAGS += -mcpu=power9 -mtune=power9
|
KOKKOS_CXXFLAGS += -mcpu=power9 -mtune=power9
|
||||||
KOKKOS_LDFLAGS += -mcpu=power9 -mtune=power9
|
KOKKOS_LDFLAGS += -mcpu=power9 -mtune=power9
|
||||||
else
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_COMPILER_NVCC), 1)
|
|
||||||
|
|
||||||
else
|
|
||||||
# Assume that this is a really a GNU compiler on P9
|
|
||||||
KOKKOS_CXXFLAGS += -mcpu=power9 -mtune=power9
|
|
||||||
KOKKOS_LDFLAGS += -mcpu=power9 -mtune=power9
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -1202,32 +1190,32 @@ endif
|
|||||||
ifeq ($(KOKKOS_INTERNAL_USE_HIP), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_HIP), 1)
|
||||||
# Lets start with adding architecture defines
|
# Lets start with adding architecture defines
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_ARCH_VEGA900), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_ARCH_VEGA900), 1)
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_HIP 900")
|
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA900")
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA900")
|
||||||
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA")
|
||||||
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx900
|
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx900
|
||||||
endif
|
endif
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_ARCH_VEGA906), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_ARCH_VEGA906), 1)
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_HIP 906")
|
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA906")
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA906")
|
||||||
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA")
|
||||||
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx906
|
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx906
|
||||||
endif
|
endif
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_ARCH_VEGA908), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_ARCH_VEGA908), 1)
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_HIP 908")
|
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA908")
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA908")
|
||||||
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA")
|
||||||
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx908
|
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx908
|
||||||
endif
|
endif
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_ARCH_VEGA90A), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_ARCH_VEGA90A), 1)
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_HIP 90A")
|
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA90A")
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA90A")
|
||||||
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ARCH_VEGA")
|
||||||
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx90a
|
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx90a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/HIP/*.cpp)
|
KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/HIP/*.cpp)
|
||||||
ifeq ($(KOKKOS_INTERNAL_ENABLE_DESUL_ATOMICS), 1)
|
KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/HIP/*.hpp)
|
||||||
|
ifeq ($(KOKKOS_INTERNAL_DISABLE_DESUL_ATOMICS), 0)
|
||||||
KOKKOS_SRC += $(KOKKOS_PATH)/core/src/desul/src/Lock_Array_HIP.cpp
|
KOKKOS_SRC += $(KOKKOS_PATH)/core/src/desul/src/Lock_Array_HIP.cpp
|
||||||
endif
|
endif
|
||||||
KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/HIP/*.hpp)
|
|
||||||
|
|
||||||
KOKKOS_CXXFLAGS+=$(KOKKOS_INTERNAL_HIP_ARCH_FLAG)
|
KOKKOS_CXXFLAGS+=$(KOKKOS_INTERNAL_HIP_ARCH_FLAG)
|
||||||
KOKKOS_LDFLAGS+=$(KOKKOS_INTERNAL_HIP_ARCH_FLAG)
|
KOKKOS_LDFLAGS+=$(KOKKOS_INTERNAL_HIP_ARCH_FLAG)
|
||||||
@ -1285,8 +1273,12 @@ ifeq ($(KOKKOS_INTERNAL_USE_SYCL), 1)
|
|||||||
KOKKOS_LDFLAGS+=$(KOKKOS_INTERNAL_SYCL_ARCH_FLAG)
|
KOKKOS_LDFLAGS+=$(KOKKOS_INTERNAL_SYCL_ARCH_FLAG)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_ENABLE_DESUL_ATOMICS), 1)
|
ifeq ($(KOKKOS_INTERNAL_DISABLE_DESUL_ATOMICS), 0)
|
||||||
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ENABLE_IMPL_DESUL_ATOMICS")
|
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ENABLE_IMPL_DESUL_ATOMICS")
|
||||||
|
else
|
||||||
|
ifeq ($(KOKKOS_INTERNAL_ENABLE_DESUL_ATOMICS), 1)
|
||||||
|
$(error Contradictory Desul atomics options: KOKKOS_OPTIONS=$(KOKKOS_OPTIONS) )
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
KOKKOS_INTERNAL_LS_CONFIG := $(shell ls KokkosCore_config.h 2>&1)
|
KOKKOS_INTERNAL_LS_CONFIG := $(shell ls KokkosCore_config.h 2>&1)
|
||||||
@ -1327,7 +1319,6 @@ ifneq ($(KOKKOS_INTERNAL_NEW_CONFIG), 0)
|
|||||||
ifeq ($(KOKKOS_INTERNAL_USE_SYCL), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_SYCL), 1)
|
||||||
tmp := $(call kokkos_append_config_header,"$H""include <fwd/Kokkos_Fwd_SYCL.hpp>","KokkosCore_Config_FwdBackend.hpp")
|
tmp := $(call kokkos_append_config_header,"$H""include <fwd/Kokkos_Fwd_SYCL.hpp>","KokkosCore_Config_FwdBackend.hpp")
|
||||||
tmp := $(call kokkos_append_config_header,"$H""include <decl/Kokkos_Declare_SYCL.hpp>","KokkosCore_Config_DeclareBackend.hpp")
|
tmp := $(call kokkos_append_config_header,"$H""include <decl/Kokkos_Declare_SYCL.hpp>","KokkosCore_Config_DeclareBackend.hpp")
|
||||||
tmp := $(call kokkos_append_config_header,"$H""include <setup/Kokkos_Setup_SYCL.hpp>","KokkosCore_Config_SetupBackend.hpp")
|
|
||||||
endif
|
endif
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_HIP), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_HIP), 1)
|
||||||
tmp := $(call kokkos_append_config_header,"$H""include <fwd/Kokkos_Fwd_HIP.hpp>","KokkosCore_Config_FwdBackend.hpp")
|
tmp := $(call kokkos_append_config_header,"$H""include <fwd/Kokkos_Fwd_HIP.hpp>","KokkosCore_Config_FwdBackend.hpp")
|
||||||
@ -1338,7 +1329,7 @@ ifneq ($(KOKKOS_INTERNAL_NEW_CONFIG), 0)
|
|||||||
tmp := $(call kokkos_append_config_header,"$H""include <fwd/Kokkos_Fwd_OPENMP.hpp>","KokkosCore_Config_FwdBackend.hpp")
|
tmp := $(call kokkos_append_config_header,"$H""include <fwd/Kokkos_Fwd_OPENMP.hpp>","KokkosCore_Config_FwdBackend.hpp")
|
||||||
tmp := $(call kokkos_append_config_header,"$H""include <decl/Kokkos_Declare_OPENMP.hpp>","KokkosCore_Config_DeclareBackend.hpp")
|
tmp := $(call kokkos_append_config_header,"$H""include <decl/Kokkos_Declare_OPENMP.hpp>","KokkosCore_Config_DeclareBackend.hpp")
|
||||||
endif
|
endif
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
|
||||||
tmp := $(call kokkos_append_config_header,"$H""include <fwd/Kokkos_Fwd_THREADS.hpp>","KokkosCore_Config_FwdBackend.hpp")
|
tmp := $(call kokkos_append_config_header,"$H""include <fwd/Kokkos_Fwd_THREADS.hpp>","KokkosCore_Config_FwdBackend.hpp")
|
||||||
tmp := $(call kokkos_append_config_header,"$H""include <decl/Kokkos_Declare_THREADS.hpp>","KokkosCore_Config_DeclareBackend.hpp")
|
tmp := $(call kokkos_append_config_header,"$H""include <decl/Kokkos_Declare_THREADS.hpp>","KokkosCore_Config_DeclareBackend.hpp")
|
||||||
endif
|
endif
|
||||||
@ -1367,7 +1358,7 @@ KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/containers/src/impl/*.cpp)
|
|||||||
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
|
||||||
KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/Cuda/*.cpp)
|
KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/Cuda/*.cpp)
|
||||||
ifeq ($(KOKKOS_INTERNAL_ENABLE_DESUL_ATOMICS), 1)
|
ifeq ($(KOKKOS_INTERNAL_DISABLE_DESUL_ATOMICS), 0)
|
||||||
KOKKOS_SRC += $(KOKKOS_PATH)/core/src/desul/src/Lock_Array_CUDA.cpp
|
KOKKOS_SRC += $(KOKKOS_PATH)/core/src/desul/src/Lock_Array_CUDA.cpp
|
||||||
endif
|
endif
|
||||||
KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/Cuda/*.hpp)
|
KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/Cuda/*.hpp)
|
||||||
@ -1419,7 +1410,7 @@ ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
|
|||||||
KOKKOS_LINK_FLAGS += $(KOKKOS_INTERNAL_OPENMP_FLAG)
|
KOKKOS_LINK_FLAGS += $(KOKKOS_INTERNAL_OPENMP_FLAG)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
|
||||||
KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/Threads/*.cpp)
|
KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/Threads/*.cpp)
|
||||||
KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/Threads/*.hpp)
|
KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/Threads/*.hpp)
|
||||||
KOKKOS_LIBS += -lpthread
|
KOKKOS_LIBS += -lpthread
|
||||||
@ -1453,14 +1444,6 @@ ifeq ($(KOKKOS_INTERNAL_USE_HPX), 1)
|
|||||||
KOKKOS_TPL_LIBRARY_NAMES += hpx
|
KOKKOS_TPL_LIBRARY_NAMES += hpx
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Explicitly set the GCC Toolchain for Clang.
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_COMPILER_CLANG), 1)
|
|
||||||
KOKKOS_INTERNAL_GCC_PATH = $(shell which g++)
|
|
||||||
KOKKOS_INTERNAL_GCC_TOOLCHAIN = $(KOKKOS_INTERNAL_GCC_PATH:/bin/g++=)
|
|
||||||
KOKKOS_CXXFLAGS += --gcc-toolchain=$(KOKKOS_INTERNAL_GCC_TOOLCHAIN)
|
|
||||||
KOKKOS_LDFLAGS += --gcc-toolchain=$(KOKKOS_INTERNAL_GCC_TOOLCHAIN)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Don't include Kokkos_HBWSpace.cpp if not using MEMKIND to avoid a link warning.
|
# Don't include Kokkos_HBWSpace.cpp if not using MEMKIND to avoid a link warning.
|
||||||
ifneq ($(KOKKOS_INTERNAL_USE_MEMKIND), 1)
|
ifneq ($(KOKKOS_INTERNAL_USE_MEMKIND), 1)
|
||||||
KOKKOS_SRC := $(filter-out $(KOKKOS_PATH)/core/src/impl/Kokkos_HBWSpace.cpp,$(KOKKOS_SRC))
|
KOKKOS_SRC := $(filter-out $(KOKKOS_PATH)/core/src/impl/Kokkos_HBWSpace.cpp,$(KOKKOS_SRC))
|
||||||
|
|||||||
@ -10,6 +10,8 @@ Kokkos_Stacktrace.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_S
|
|||||||
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Stacktrace.cpp
|
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Stacktrace.cpp
|
||||||
Kokkos_ExecPolicy.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_ExecPolicy.cpp
|
Kokkos_ExecPolicy.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_ExecPolicy.cpp
|
||||||
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_ExecPolicy.cpp
|
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_ExecPolicy.cpp
|
||||||
|
Kokkos_Command_Line_Parsing.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_Command_Line_Parsing.cpp
|
||||||
|
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Command_Line_Parsing.cpp
|
||||||
Kokkos_HostSpace.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_HostSpace.cpp
|
Kokkos_HostSpace.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_HostSpace.cpp
|
||||||
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_HostSpace.cpp
|
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_HostSpace.cpp
|
||||||
Kokkos_hwloc.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_hwloc.cpp
|
Kokkos_hwloc.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_hwloc.cpp
|
||||||
@ -72,7 +74,7 @@ Lock_Array_HIP.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/desul/src/Lock_A
|
|||||||
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/desul/src/Lock_Array_HIP.cpp
|
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/desul/src/Lock_Array_HIP.cpp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
|
||||||
Kokkos_ThreadsExec_base.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec_base.cpp
|
Kokkos_ThreadsExec_base.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec_base.cpp
|
||||||
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec_base.cpp
|
$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec_base.cpp
|
||||||
Kokkos_ThreadsExec.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec.cpp
|
Kokkos_ThreadsExec.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec.cpp
|
||||||
|
|||||||
@ -48,14 +48,14 @@ For specifics see the LICENSE file contained in the repository or distribution.
|
|||||||
Generally Kokkos should work with all compiler versions newer than the minimum.
|
Generally Kokkos should work with all compiler versions newer than the minimum.
|
||||||
However as in all sufficiently complex enough code, we have to work around compiler
|
However as in all sufficiently complex enough code, we have to work around compiler
|
||||||
bugs with almost all compilers. So compiler versions we don't test may have issues
|
bugs with almost all compilers. So compiler versions we don't test may have issues
|
||||||
we are unaware off.
|
we are unaware of.
|
||||||
|
|
||||||
* GCC: 5.3.0
|
* GCC: 5.3.0
|
||||||
* Clang: 4.0.0
|
* Clang: 4.0.0
|
||||||
* Intel: 17.0.1
|
* Intel: 17.0.1
|
||||||
* NVCC: 9.2.88
|
* NVCC: 9.2.88
|
||||||
* NVC++: 21.5
|
* NVC++: 21.5
|
||||||
* ROCM: 4.3
|
* ROCm: 4.3
|
||||||
* MSVC: 19.29
|
* MSVC: 19.29
|
||||||
* IBM XL: 16.1.1
|
* IBM XL: 16.1.1
|
||||||
* Fujitsu: 4.5.0
|
* Fujitsu: 4.5.0
|
||||||
@ -70,7 +70,7 @@ we are unaware off.
|
|||||||
* MSVC: 19.29
|
* MSVC: 19.29
|
||||||
* ARM/Clang: 20.1
|
* ARM/Clang: 20.1
|
||||||
* IBM XL: 16.1.1
|
* IBM XL: 16.1.1
|
||||||
* ROCM: 4.3.0
|
* ROCm: 4.3.0
|
||||||
|
|
||||||
### Build system:
|
### Build system:
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ we are unaware off.
|
|||||||
|
|
||||||
Primary tested compiler are passing in release mode
|
Primary tested compiler are passing in release mode
|
||||||
with warnings as errors. They also are tested with a comprehensive set of
|
with warnings as errors. They also are tested with a comprehensive set of
|
||||||
backend combinations (i.e. OpenMP, Pthreads, Serial, OpenMP+Serial, ...).
|
backend combinations (i.e. OpenMP, Threads, Serial, OpenMP+Serial, ...).
|
||||||
We are using the following set of flags:
|
We are using the following set of flags:
|
||||||
* GCC:
|
* GCC:
|
||||||
````
|
````
|
||||||
@ -193,7 +193,7 @@ The main reason is that you may otherwise need many different
|
|||||||
configurations of Kokkos installed depending on the required compile time
|
configurations of Kokkos installed depending on the required compile time
|
||||||
features an application needs. For example there is only one default
|
features an application needs. For example there is only one default
|
||||||
execution space, which means you need different installations to have OpenMP
|
execution space, which means you need different installations to have OpenMP
|
||||||
or Pthreads as the default space. Also for the CUDA backend there are certain
|
or C++ threads as the default space. Also for the CUDA backend there are certain
|
||||||
choices, such as allowing relocatable device code, which must be made at
|
choices, such as allowing relocatable device code, which must be made at
|
||||||
installation time. Building Kokkos inline uses largely the same process
|
installation time. Building Kokkos inline uses largely the same process
|
||||||
as compiling an application against an installed Kokkos library.
|
as compiling an application against an installed Kokkos library.
|
||||||
|
|||||||
@ -25,19 +25,21 @@ This can be limited by adding a `packages.yaml` to your `$HOME/.spack` folder th
|
|||||||
````yaml
|
````yaml
|
||||||
packages:
|
packages:
|
||||||
cuda:
|
cuda:
|
||||||
modules:
|
|
||||||
cuda@10.1.243: [cuda/10.1.243]
|
|
||||||
paths:
|
|
||||||
cuda@10.1.243:
|
|
||||||
/opt/local/ppc64le-pwr8-nvidia/cuda/10.1.243
|
|
||||||
buildable: false
|
buildable: false
|
||||||
|
externals:
|
||||||
|
- prefix: /opt/local/ppc64le-pwr8-nvidia/cuda/10.1.243
|
||||||
|
spec: cuda@10.1.243
|
||||||
|
- modules:
|
||||||
|
- cuda/10.1.243
|
||||||
|
spec: cuda@10.1.243
|
||||||
cmake:
|
cmake:
|
||||||
modules:
|
|
||||||
cmake: [cmake/3.16.8]
|
|
||||||
paths:
|
|
||||||
cmake:
|
|
||||||
/opt/local/ppc64le/cmake/3.16.8
|
|
||||||
buildable: false
|
buildable: false
|
||||||
|
externals:
|
||||||
|
- prefix: /opt/local/ppc64le/cmake/3.16.8
|
||||||
|
spec: cmake@3.16.8
|
||||||
|
- modules:
|
||||||
|
- cmake/3.16.8
|
||||||
|
spec: cmake@3.16.8
|
||||||
````
|
````
|
||||||
The `modules` entry is only necessary on systems that require loading Modules (i.e. most DOE systems).
|
The `modules` entry is only necessary on systems that require loading Modules (i.e. most DOE systems).
|
||||||
The `buildable` flag is useful to make sure Spack crashes if there is a path error,
|
The `buildable` flag is useful to make sure Spack crashes if there is a path error,
|
||||||
|
|||||||
@ -10,6 +10,7 @@ KOKKOS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
|||||||
FILE(GLOB ALGO_HEADERS *.hpp)
|
FILE(GLOB ALGO_HEADERS *.hpp)
|
||||||
FILE(GLOB ALGO_SOURCES *.cpp)
|
FILE(GLOB ALGO_SOURCES *.cpp)
|
||||||
LIST(APPEND ALGO_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}_config.h)
|
LIST(APPEND ALGO_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}_config.h)
|
||||||
|
APPEND_GLOB(ALGO_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/std_algorithms/*.hpp)
|
||||||
|
|
||||||
INSTALL (
|
INSTALL (
|
||||||
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
|
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
|
||||||
|
|||||||
@ -466,6 +466,25 @@ struct rand<Generator, Kokkos::Experimental::half_t> {
|
|||||||
};
|
};
|
||||||
#endif // defined(KOKKOS_HALF_T_IS_FLOAT) && !KOKKOS_HALF_T_IS_FLOAT
|
#endif // defined(KOKKOS_HALF_T_IS_FLOAT) && !KOKKOS_HALF_T_IS_FLOAT
|
||||||
|
|
||||||
|
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||||
|
template <class Generator>
|
||||||
|
struct rand<Generator, Kokkos::Experimental::bhalf_t> {
|
||||||
|
using bhalf = Kokkos::Experimental::bhalf_t;
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
static bhalf max() { return bhalf(1.0); }
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
static bhalf draw(Generator& gen) { return bhalf(gen.frand()); }
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
static bhalf draw(Generator& gen, const bhalf& range) {
|
||||||
|
return bhalf(gen.frand(float(range)));
|
||||||
|
}
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
static bhalf draw(Generator& gen, const bhalf& start, const bhalf& end) {
|
||||||
|
return bhalf(gen.frand(float(start), float(end)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||||
|
|
||||||
template <class Generator>
|
template <class Generator>
|
||||||
struct rand<Generator, float> {
|
struct rand<Generator, float> {
|
||||||
KOKKOS_INLINE_FUNCTION
|
KOKKOS_INLINE_FUNCTION
|
||||||
@ -617,24 +636,23 @@ struct Random_XorShift1024_UseCArrayState<Kokkos::Experimental::OpenMPTarget>
|
|||||||
: std::false_type {};
|
: std::false_type {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <class ExecutionSpace>
|
template <class DeviceType>
|
||||||
struct Random_UniqueIndex {
|
struct Random_UniqueIndex {
|
||||||
using locks_view_type = View<int**, ExecutionSpace>;
|
using locks_view_type = View<int**, DeviceType>;
|
||||||
KOKKOS_FUNCTION
|
KOKKOS_FUNCTION
|
||||||
static int get_state_idx(const locks_view_type) {
|
static int get_state_idx(const locks_view_type) {
|
||||||
#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
|
KOKKOS_IF_ON_HOST(
|
||||||
const int i = ExecutionSpace::impl_hardware_thread_id();
|
(return DeviceType::execution_space::impl_hardware_thread_id();))
|
||||||
return i;
|
|
||||||
#else
|
KOKKOS_IF_ON_DEVICE((return 0;))
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef KOKKOS_ENABLE_CUDA
|
#ifdef KOKKOS_ENABLE_CUDA
|
||||||
template <>
|
template <class MemorySpace>
|
||||||
struct Random_UniqueIndex<Kokkos::Cuda> {
|
struct Random_UniqueIndex<Kokkos::Device<Kokkos::Cuda, MemorySpace>> {
|
||||||
using locks_view_type = View<int**, Kokkos::Cuda>;
|
using locks_view_type =
|
||||||
|
View<int**, Kokkos::Device<Kokkos::Cuda, MemorySpace>>;
|
||||||
KOKKOS_FUNCTION
|
KOKKOS_FUNCTION
|
||||||
static int get_state_idx(const locks_view_type& locks_) {
|
static int get_state_idx(const locks_view_type& locks_) {
|
||||||
#ifdef __CUDA_ARCH__
|
#ifdef __CUDA_ARCH__
|
||||||
@ -660,9 +678,11 @@ struct Random_UniqueIndex<Kokkos::Cuda> {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KOKKOS_ENABLE_HIP
|
#ifdef KOKKOS_ENABLE_HIP
|
||||||
template <>
|
template <class MemorySpace>
|
||||||
struct Random_UniqueIndex<Kokkos::Experimental::HIP> {
|
struct Random_UniqueIndex<
|
||||||
using locks_view_type = View<int**, Kokkos::Experimental::HIP>;
|
Kokkos::Device<Kokkos::Experimental::HIP, MemorySpace>> {
|
||||||
|
using locks_view_type =
|
||||||
|
View<int**, Kokkos::Device<Kokkos::Experimental::HIP, MemorySpace>>;
|
||||||
KOKKOS_FUNCTION
|
KOKKOS_FUNCTION
|
||||||
static int get_state_idx(const locks_view_type& locks_) {
|
static int get_state_idx(const locks_view_type& locks_) {
|
||||||
#ifdef __HIP_DEVICE_COMPILE__
|
#ifdef __HIP_DEVICE_COMPILE__
|
||||||
@ -688,18 +708,37 @@ struct Random_UniqueIndex<Kokkos::Experimental::HIP> {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KOKKOS_ENABLE_SYCL
|
#ifdef KOKKOS_ENABLE_SYCL
|
||||||
template <>
|
template <class MemorySpace>
|
||||||
struct Random_UniqueIndex<Kokkos::Experimental::SYCL> {
|
struct Random_UniqueIndex<
|
||||||
using locks_view_type = View<int**, Kokkos::Experimental::SYCL>;
|
Kokkos::Device<Kokkos::Experimental::SYCL, MemorySpace>> {
|
||||||
|
using locks_view_type =
|
||||||
|
View<int**, Kokkos::Device<Kokkos::Experimental::SYCL, MemorySpace>>;
|
||||||
KOKKOS_FUNCTION
|
KOKKOS_FUNCTION
|
||||||
static int get_state_idx(const locks_view_type& locks_) {
|
static int get_state_idx(const locks_view_type& locks_) {
|
||||||
#ifdef KOKKOS_ARCH_INTEL_GPU
|
auto item = sycl::ext::oneapi::experimental::this_nd_item<3>();
|
||||||
int i = Kokkos::Impl::clock_tic() % locks_.extent(0);
|
std::size_t threadIdx[3] = {item.get_local_id(2), item.get_local_id(1),
|
||||||
#else
|
item.get_local_id(0)};
|
||||||
int i = 0;
|
std::size_t blockIdx[3] = {item.get_group(2), item.get_group(1),
|
||||||
#endif
|
item.get_group(0)};
|
||||||
|
std::size_t blockDim[3] = {item.get_local_range(2), item.get_local_range(1),
|
||||||
|
item.get_local_range(0)};
|
||||||
|
std::size_t gridDim[3] = {
|
||||||
|
item.get_global_range(2) / item.get_local_range(2),
|
||||||
|
item.get_global_range(1) / item.get_local_range(1),
|
||||||
|
item.get_global_range(0) / item.get_local_range(0)};
|
||||||
|
const int i_offset =
|
||||||
|
(threadIdx[0] * blockDim[1] + threadIdx[1]) * blockDim[2] +
|
||||||
|
threadIdx[2];
|
||||||
|
int i =
|
||||||
|
(((blockIdx[0] * gridDim[1] + blockIdx[1]) * gridDim[2] + blockIdx[2]) *
|
||||||
|
blockDim[0] * blockDim[1] * blockDim[2] +
|
||||||
|
i_offset) %
|
||||||
|
locks_.extent(0);
|
||||||
while (Kokkos::atomic_compare_exchange(&locks_(i, 0), 0, 1)) {
|
while (Kokkos::atomic_compare_exchange(&locks_(i, 0), 0, 1)) {
|
||||||
i = (i + 1) % static_cast<int>(locks_.extent(0));
|
i += blockDim[0] * blockDim[1] * blockDim[2];
|
||||||
|
if (i >= static_cast<int>(locks_.extent(0))) {
|
||||||
|
i = i_offset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -707,9 +746,12 @@ struct Random_UniqueIndex<Kokkos::Experimental::SYCL> {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KOKKOS_ENABLE_OPENMPTARGET
|
#ifdef KOKKOS_ENABLE_OPENMPTARGET
|
||||||
template <>
|
template <class MemorySpace>
|
||||||
struct Random_UniqueIndex<Kokkos::Experimental::OpenMPTarget> {
|
struct Random_UniqueIndex<
|
||||||
using locks_view_type = View<int**, Kokkos::Experimental::OpenMPTarget>;
|
Kokkos::Device<Kokkos::Experimental::OpenMPTarget, MemorySpace>> {
|
||||||
|
using locks_view_type =
|
||||||
|
View<int**,
|
||||||
|
Kokkos::Device<Kokkos::Experimental::OpenMPTarget, MemorySpace>>;
|
||||||
KOKKOS_FUNCTION
|
KOKKOS_FUNCTION
|
||||||
static int get_state_idx(const locks_view_type& locks) {
|
static int get_state_idx(const locks_view_type& locks) {
|
||||||
const int team_size = omp_get_num_threads();
|
const int team_size = omp_get_num_threads();
|
||||||
@ -873,10 +915,13 @@ class Random_XorShift64 {
|
|||||||
|
|
||||||
template <class DeviceType = Kokkos::DefaultExecutionSpace>
|
template <class DeviceType = Kokkos::DefaultExecutionSpace>
|
||||||
class Random_XorShift64_Pool {
|
class Random_XorShift64_Pool {
|
||||||
|
public:
|
||||||
|
using device_type = typename DeviceType::device_type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using execution_space = typename DeviceType::execution_space;
|
using execution_space = typename device_type::execution_space;
|
||||||
using locks_type = View<int**, execution_space>;
|
using locks_type = View<int**, device_type>;
|
||||||
using state_data_type = View<uint64_t**, DeviceType>;
|
using state_data_type = View<uint64_t**, device_type>;
|
||||||
locks_type locks_;
|
locks_type locks_;
|
||||||
state_data_type state_;
|
state_data_type state_;
|
||||||
int num_states_;
|
int num_states_;
|
||||||
@ -884,7 +929,6 @@ class Random_XorShift64_Pool {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using generator_type = Random_XorShift64<DeviceType>;
|
using generator_type = Random_XorShift64<DeviceType>;
|
||||||
using device_type = DeviceType;
|
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
KOKKOS_INLINE_FUNCTION
|
||||||
Random_XorShift64_Pool() {
|
Random_XorShift64_Pool() {
|
||||||
@ -923,8 +967,10 @@ class Random_XorShift64_Pool {
|
|||||||
state_ = state_data_type("Kokkos::Random_XorShift64::state", num_states_,
|
state_ = state_data_type("Kokkos::Random_XorShift64::state", num_states_,
|
||||||
padding_);
|
padding_);
|
||||||
|
|
||||||
typename state_data_type::HostMirror h_state = create_mirror_view(state_);
|
typename state_data_type::HostMirror h_state =
|
||||||
typename locks_type::HostMirror h_lock = create_mirror_view(locks_);
|
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, state_);
|
||||||
|
typename locks_type::HostMirror h_lock =
|
||||||
|
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, locks_);
|
||||||
|
|
||||||
// Execute on the HostMirror's default execution space.
|
// Execute on the HostMirror's default execution space.
|
||||||
Random_XorShift64<typename state_data_type::HostMirror::execution_space>
|
Random_XorShift64<typename state_data_type::HostMirror::execution_space>
|
||||||
@ -947,8 +993,7 @@ class Random_XorShift64_Pool {
|
|||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
KOKKOS_INLINE_FUNCTION
|
||||||
Random_XorShift64<DeviceType> get_state() const {
|
Random_XorShift64<DeviceType> get_state() const {
|
||||||
const int i =
|
const int i = Impl::Random_UniqueIndex<device_type>::get_state_idx(locks_);
|
||||||
Impl::Random_UniqueIndex<execution_space>::get_state_idx(locks_);
|
|
||||||
return Random_XorShift64<DeviceType>(state_(i, 0), i);
|
return Random_XorShift64<DeviceType>(state_(i, 0), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1119,11 +1164,14 @@ class Random_XorShift1024 {
|
|||||||
|
|
||||||
template <class DeviceType = Kokkos::DefaultExecutionSpace>
|
template <class DeviceType = Kokkos::DefaultExecutionSpace>
|
||||||
class Random_XorShift1024_Pool {
|
class Random_XorShift1024_Pool {
|
||||||
|
public:
|
||||||
|
using device_type = typename DeviceType::device_type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using execution_space = typename DeviceType::execution_space;
|
using execution_space = typename device_type::execution_space;
|
||||||
using locks_type = View<int**, execution_space>;
|
using locks_type = View<int**, device_type>;
|
||||||
using int_view_type = View<int**, DeviceType>;
|
using int_view_type = View<int**, device_type>;
|
||||||
using state_data_type = View<uint64_t * [16], DeviceType>;
|
using state_data_type = View<uint64_t * [16], device_type>;
|
||||||
|
|
||||||
locks_type locks_;
|
locks_type locks_;
|
||||||
state_data_type state_;
|
state_data_type state_;
|
||||||
@ -1135,8 +1183,6 @@ class Random_XorShift1024_Pool {
|
|||||||
public:
|
public:
|
||||||
using generator_type = Random_XorShift1024<DeviceType>;
|
using generator_type = Random_XorShift1024<DeviceType>;
|
||||||
|
|
||||||
using device_type = DeviceType;
|
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
KOKKOS_INLINE_FUNCTION
|
||||||
Random_XorShift1024_Pool() { num_states_ = 0; }
|
Random_XorShift1024_Pool() { num_states_ = 0; }
|
||||||
|
|
||||||
@ -1175,9 +1221,12 @@ class Random_XorShift1024_Pool {
|
|||||||
state_ = state_data_type("Kokkos::Random_XorShift1024::state", num_states_);
|
state_ = state_data_type("Kokkos::Random_XorShift1024::state", num_states_);
|
||||||
p_ = int_view_type("Kokkos::Random_XorShift1024::p", num_states_, padding_);
|
p_ = int_view_type("Kokkos::Random_XorShift1024::p", num_states_, padding_);
|
||||||
|
|
||||||
typename state_data_type::HostMirror h_state = create_mirror_view(state_);
|
typename state_data_type::HostMirror h_state =
|
||||||
typename locks_type::HostMirror h_lock = create_mirror_view(locks_);
|
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, state_);
|
||||||
typename int_view_type::HostMirror h_p = create_mirror_view(p_);
|
typename locks_type::HostMirror h_lock =
|
||||||
|
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, locks_);
|
||||||
|
typename int_view_type::HostMirror h_p =
|
||||||
|
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, p_);
|
||||||
|
|
||||||
// Execute on the HostMirror's default execution space.
|
// Execute on the HostMirror's default execution space.
|
||||||
Random_XorShift64<typename state_data_type::HostMirror::execution_space>
|
Random_XorShift64<typename state_data_type::HostMirror::execution_space>
|
||||||
@ -1203,8 +1252,7 @@ class Random_XorShift1024_Pool {
|
|||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
KOKKOS_INLINE_FUNCTION
|
||||||
Random_XorShift1024<DeviceType> get_state() const {
|
Random_XorShift1024<DeviceType> get_state() const {
|
||||||
const int i =
|
const int i = Impl::Random_UniqueIndex<device_type>::get_state_idx(locks_);
|
||||||
Impl::Random_UniqueIndex<execution_space>::get_state_idx(locks_);
|
|
||||||
return Random_XorShift1024<DeviceType>(state_, p_(i, 0), i);
|
return Random_XorShift1024<DeviceType>(state_, p_(i, 0), i);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1224,265 +1272,34 @@ class Random_XorShift1024_Pool {
|
|||||||
|
|
||||||
namespace Impl {
|
namespace Impl {
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, int loops, int rank,
|
|
||||||
class IndexType>
|
|
||||||
struct fill_random_functor_range;
|
|
||||||
template <class ViewType, class RandomPool, int loops, int rank,
|
template <class ViewType, class RandomPool, int loops, int rank,
|
||||||
class IndexType>
|
class IndexType>
|
||||||
struct fill_random_functor_begin_end;
|
struct fill_random_functor_begin_end;
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 1, IndexType> {
|
struct fill_random_functor_begin_end<ViewType, RandomPool, loops, 0,
|
||||||
|
IndexType> {
|
||||||
using execution_space = typename ViewType::execution_space;
|
using execution_space = typename ViewType::execution_space;
|
||||||
ViewType a;
|
ViewType a;
|
||||||
RandomPool rand_pool;
|
RandomPool rand_pool;
|
||||||
typename ViewType::const_value_type range;
|
typename ViewType::const_value_type begin, end;
|
||||||
|
|
||||||
using Rand = rand<typename RandomPool::generator_type,
|
using Rand = rand<typename RandomPool::generator_type,
|
||||||
typename ViewType::non_const_value_type>;
|
typename ViewType::non_const_value_type>;
|
||||||
|
|
||||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
|
||||||
typename ViewType::const_value_type range_)
|
typename ViewType::const_value_type begin_,
|
||||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
typename ViewType::const_value_type end_)
|
||||||
|
: a(a_), rand_pool(rand_pool_), begin(begin_), end(end_) {}
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
KOKKOS_INLINE_FUNCTION
|
||||||
void operator()(const IndexType& i) const {
|
void operator()(IndexType) const {
|
||||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
typename RandomPool::generator_type gen = rand_pool.get_state();
|
||||||
for (IndexType j = 0; j < loops; j++) {
|
a() = Rand::draw(gen, begin, end);
|
||||||
const IndexType idx = i * loops + j;
|
|
||||||
if (idx < static_cast<IndexType>(a.extent(0)))
|
|
||||||
a(idx) = Rand::draw(gen, range);
|
|
||||||
}
|
|
||||||
rand_pool.free_state(gen);
|
rand_pool.free_state(gen);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
|
||||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 2, IndexType> {
|
|
||||||
using execution_space = typename ViewType::execution_space;
|
|
||||||
ViewType a;
|
|
||||||
RandomPool rand_pool;
|
|
||||||
typename ViewType::const_value_type range;
|
|
||||||
|
|
||||||
using Rand = rand<typename RandomPool::generator_type,
|
|
||||||
typename ViewType::non_const_value_type>;
|
|
||||||
|
|
||||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
|
||||||
typename ViewType::const_value_type range_)
|
|
||||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
|
||||||
void operator()(IndexType i) const {
|
|
||||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
|
||||||
for (IndexType j = 0; j < loops; j++) {
|
|
||||||
const IndexType idx = i * loops + j;
|
|
||||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
|
||||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
|
||||||
a(idx, k) = Rand::draw(gen, range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rand_pool.free_state(gen);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
|
||||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 3, IndexType> {
|
|
||||||
using execution_space = typename ViewType::execution_space;
|
|
||||||
ViewType a;
|
|
||||||
RandomPool rand_pool;
|
|
||||||
typename ViewType::const_value_type range;
|
|
||||||
|
|
||||||
using Rand = rand<typename RandomPool::generator_type,
|
|
||||||
typename ViewType::non_const_value_type>;
|
|
||||||
|
|
||||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
|
||||||
typename ViewType::const_value_type range_)
|
|
||||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
|
||||||
void operator()(IndexType i) const {
|
|
||||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
|
||||||
for (IndexType j = 0; j < loops; j++) {
|
|
||||||
const IndexType idx = i * loops + j;
|
|
||||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
|
||||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
|
||||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
|
||||||
a(idx, k, l) = Rand::draw(gen, range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rand_pool.free_state(gen);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
|
||||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 4, IndexType> {
|
|
||||||
using execution_space = typename ViewType::execution_space;
|
|
||||||
ViewType a;
|
|
||||||
RandomPool rand_pool;
|
|
||||||
typename ViewType::const_value_type range;
|
|
||||||
|
|
||||||
using Rand = rand<typename RandomPool::generator_type,
|
|
||||||
typename ViewType::non_const_value_type>;
|
|
||||||
|
|
||||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
|
||||||
typename ViewType::const_value_type range_)
|
|
||||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
|
||||||
void operator()(IndexType i) const {
|
|
||||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
|
||||||
for (IndexType j = 0; j < loops; j++) {
|
|
||||||
const IndexType idx = i * loops + j;
|
|
||||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
|
||||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
|
||||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
|
||||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
|
||||||
a(idx, k, l, m) = Rand::draw(gen, range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rand_pool.free_state(gen);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
|
||||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 5, IndexType> {
|
|
||||||
using execution_space = typename ViewType::execution_space;
|
|
||||||
ViewType a;
|
|
||||||
RandomPool rand_pool;
|
|
||||||
typename ViewType::const_value_type range;
|
|
||||||
|
|
||||||
using Rand = rand<typename RandomPool::generator_type,
|
|
||||||
typename ViewType::non_const_value_type>;
|
|
||||||
|
|
||||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
|
||||||
typename ViewType::const_value_type range_)
|
|
||||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
|
||||||
void operator()(IndexType i) const {
|
|
||||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
|
||||||
for (IndexType j = 0; j < loops; j++) {
|
|
||||||
const IndexType idx = i * loops + j;
|
|
||||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
|
||||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
|
||||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
|
||||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
|
||||||
for (IndexType n = 0; n < static_cast<IndexType>(a.extent(4));
|
|
||||||
n++)
|
|
||||||
a(idx, k, l, m, n) = Rand::draw(gen, range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rand_pool.free_state(gen);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
|
||||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 6, IndexType> {
|
|
||||||
using execution_space = typename ViewType::execution_space;
|
|
||||||
ViewType a;
|
|
||||||
RandomPool rand_pool;
|
|
||||||
typename ViewType::const_value_type range;
|
|
||||||
|
|
||||||
using Rand = rand<typename RandomPool::generator_type,
|
|
||||||
typename ViewType::non_const_value_type>;
|
|
||||||
|
|
||||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
|
||||||
typename ViewType::const_value_type range_)
|
|
||||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
|
||||||
void operator()(IndexType i) const {
|
|
||||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
|
||||||
for (IndexType j = 0; j < loops; j++) {
|
|
||||||
const IndexType idx = i * loops + j;
|
|
||||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
|
||||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
|
||||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
|
||||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
|
||||||
for (IndexType n = 0; n < static_cast<IndexType>(a.extent(4));
|
|
||||||
n++)
|
|
||||||
for (IndexType o = 0; o < static_cast<IndexType>(a.extent(5));
|
|
||||||
o++)
|
|
||||||
a(idx, k, l, m, n, o) = Rand::draw(gen, range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rand_pool.free_state(gen);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
|
||||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 7, IndexType> {
|
|
||||||
using execution_space = typename ViewType::execution_space;
|
|
||||||
ViewType a;
|
|
||||||
RandomPool rand_pool;
|
|
||||||
typename ViewType::const_value_type range;
|
|
||||||
|
|
||||||
using Rand = rand<typename RandomPool::generator_type,
|
|
||||||
typename ViewType::non_const_value_type>;
|
|
||||||
|
|
||||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
|
||||||
typename ViewType::const_value_type range_)
|
|
||||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
|
||||||
void operator()(IndexType i) const {
|
|
||||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
|
||||||
for (IndexType j = 0; j < loops; j++) {
|
|
||||||
const IndexType idx = i * loops + j;
|
|
||||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
|
||||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
|
||||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
|
||||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
|
||||||
for (IndexType n = 0; n < static_cast<IndexType>(a.extent(4));
|
|
||||||
n++)
|
|
||||||
for (IndexType o = 0; o < static_cast<IndexType>(a.extent(5));
|
|
||||||
o++)
|
|
||||||
for (IndexType p = 0; p < static_cast<IndexType>(a.extent(6));
|
|
||||||
p++)
|
|
||||||
a(idx, k, l, m, n, o, p) = Rand::draw(gen, range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rand_pool.free_state(gen);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
|
||||||
struct fill_random_functor_range<ViewType, RandomPool, loops, 8, IndexType> {
|
|
||||||
using execution_space = typename ViewType::execution_space;
|
|
||||||
ViewType a;
|
|
||||||
RandomPool rand_pool;
|
|
||||||
typename ViewType::const_value_type range;
|
|
||||||
|
|
||||||
using Rand = rand<typename RandomPool::generator_type,
|
|
||||||
typename ViewType::non_const_value_type>;
|
|
||||||
|
|
||||||
fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
|
|
||||||
typename ViewType::const_value_type range_)
|
|
||||||
: a(a_), rand_pool(rand_pool_), range(range_) {}
|
|
||||||
|
|
||||||
KOKKOS_INLINE_FUNCTION
|
|
||||||
void operator()(IndexType i) const {
|
|
||||||
typename RandomPool::generator_type gen = rand_pool.get_state();
|
|
||||||
for (IndexType j = 0; j < loops; j++) {
|
|
||||||
const IndexType idx = i * loops + j;
|
|
||||||
if (idx < static_cast<IndexType>(a.extent(0))) {
|
|
||||||
for (IndexType k = 0; k < static_cast<IndexType>(a.extent(1)); k++)
|
|
||||||
for (IndexType l = 0; l < static_cast<IndexType>(a.extent(2)); l++)
|
|
||||||
for (IndexType m = 0; m < static_cast<IndexType>(a.extent(3)); m++)
|
|
||||||
for (IndexType n = 0; n < static_cast<IndexType>(a.extent(4));
|
|
||||||
n++)
|
|
||||||
for (IndexType o = 0; o < static_cast<IndexType>(a.extent(5));
|
|
||||||
o++)
|
|
||||||
for (IndexType p = 0; p < static_cast<IndexType>(a.extent(6));
|
|
||||||
p++)
|
|
||||||
for (IndexType q = 0;
|
|
||||||
q < static_cast<IndexType>(a.extent(7)); q++)
|
|
||||||
a(idx, k, l, m, n, o, p, q) = Rand::draw(gen, range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rand_pool.free_state(gen);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <class ViewType, class RandomPool, int loops, class IndexType>
|
template <class ViewType, class RandomPool, int loops, class IndexType>
|
||||||
struct fill_random_functor_begin_end<ViewType, RandomPool, loops, 1,
|
struct fill_random_functor_begin_end<ViewType, RandomPool, loops, 1,
|
||||||
IndexType> {
|
IndexType> {
|
||||||
@ -1752,19 +1569,6 @@ struct fill_random_functor_begin_end<ViewType, RandomPool, loops, 8,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Impl
|
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, class IndexType = int64_t>
|
|
||||||
void fill_random(ViewType a, RandomPool g,
|
|
||||||
typename ViewType::const_value_type range) {
|
|
||||||
int64_t LDA = a.extent(0);
|
|
||||||
if (LDA > 0)
|
|
||||||
parallel_for("Kokkos::fill_random", (LDA + 127) / 128,
|
|
||||||
Impl::fill_random_functor_range<ViewType, RandomPool, 128,
|
|
||||||
ViewType::Rank, IndexType>(
|
|
||||||
a, g, range));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ViewType, class RandomPool, class IndexType = int64_t>
|
template <class ViewType, class RandomPool, class IndexType = int64_t>
|
||||||
void fill_random(ViewType a, RandomPool g,
|
void fill_random(ViewType a, RandomPool g,
|
||||||
typename ViewType::const_value_type begin,
|
typename ViewType::const_value_type begin,
|
||||||
@ -1776,6 +1580,23 @@ void fill_random(ViewType a, RandomPool g,
|
|||||||
ViewType::Rank, IndexType>(
|
ViewType::Rank, IndexType>(
|
||||||
a, g, begin, end));
|
a, g, begin, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Impl
|
||||||
|
|
||||||
|
template <class ViewType, class RandomPool, class IndexType = int64_t>
|
||||||
|
void fill_random(ViewType a, RandomPool g,
|
||||||
|
typename ViewType::const_value_type begin,
|
||||||
|
typename ViewType::const_value_type end) {
|
||||||
|
Impl::apply_to_view_of_static_rank(
|
||||||
|
[&](auto dst) { Kokkos::Impl::fill_random(dst, g, begin, end); }, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType, class RandomPool, class IndexType = int64_t>
|
||||||
|
void fill_random(ViewType a, RandomPool g,
|
||||||
|
typename ViewType::const_value_type range) {
|
||||||
|
fill_random(a, g, 0, range);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Kokkos
|
} // namespace Kokkos
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -437,16 +437,41 @@ struct BinOp1D {
|
|||||||
BinOp1D(int max_bins__, typename KeyViewType::const_value_type min,
|
BinOp1D(int max_bins__, typename KeyViewType::const_value_type min,
|
||||||
typename KeyViewType::const_value_type max)
|
typename KeyViewType::const_value_type max)
|
||||||
: max_bins_(max_bins__ + 1),
|
: max_bins_(max_bins__ + 1),
|
||||||
mul_(1.0 * max_bins__ / (max - min)),
|
// Cast to int64_t to avoid possible overflow when using integer
|
||||||
|
mul_(std::is_integral<typename KeyViewType::const_value_type>::value
|
||||||
|
? 1.0 * max_bins__ / (int64_t(max) - int64_t(min))
|
||||||
|
: 1.0 * max_bins__ / (max - min)),
|
||||||
range_(max - min),
|
range_(max - min),
|
||||||
min_(min) {}
|
min_(min) {
|
||||||
|
// For integral types the number of bins may be larger than the range
|
||||||
|
// in which case we can exactly have one unique value per bin
|
||||||
|
// and then don't need to sort bins.
|
||||||
|
if (std::is_integral<typename KeyViewType::const_value_type>::value &&
|
||||||
|
static_cast<uint64_t>(range_) <= static_cast<uint64_t>(max_bins__)) {
|
||||||
|
mul_ = 1.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Determine bin index from key value
|
// Determine bin index from key value
|
||||||
template <class ViewType>
|
template <
|
||||||
|
class ViewType,
|
||||||
|
std::enable_if_t<!std::is_integral<typename ViewType::value_type>::value,
|
||||||
|
bool> = true>
|
||||||
KOKKOS_INLINE_FUNCTION int bin(ViewType& keys, const int& i) const {
|
KOKKOS_INLINE_FUNCTION int bin(ViewType& keys, const int& i) const {
|
||||||
return int(mul_ * (keys(i) - min_));
|
return int(mul_ * (keys(i) - min_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine bin index from key value
|
||||||
|
template <
|
||||||
|
class ViewType,
|
||||||
|
std::enable_if_t<std::is_integral<typename ViewType::value_type>::value,
|
||||||
|
bool> = true>
|
||||||
|
KOKKOS_INLINE_FUNCTION int bin(ViewType& keys, const int& i) const {
|
||||||
|
// The cast to int64_t is necessary because otherwise HIP returns the wrong
|
||||||
|
// result.
|
||||||
|
return int(mul_ * (int64_t(keys(i)) - int64_t(min_)));
|
||||||
|
}
|
||||||
|
|
||||||
// Return maximum bin index + 1
|
// Return maximum bin index + 1
|
||||||
KOKKOS_INLINE_FUNCTION
|
KOKKOS_INLINE_FUNCTION
|
||||||
int max_bins() const { return max_bins_; }
|
int max_bins() const { return max_bins_; }
|
||||||
@ -564,8 +589,26 @@ std::enable_if_t<Kokkos::is_execution_space<ExecutionSpace>::value> sort(
|
|||||||
exec, 0, view.extent(0)),
|
exec, 0, view.extent(0)),
|
||||||
Impl::min_max_functor<ViewType>(view), reducer);
|
Impl::min_max_functor<ViewType>(view), reducer);
|
||||||
if (result.min_val == result.max_val) return;
|
if (result.min_val == result.max_val) return;
|
||||||
|
// For integral types the number of bins may be larger than the range
|
||||||
|
// in which case we can exactly have one unique value per bin
|
||||||
|
// and then don't need to sort bins.
|
||||||
|
bool sort_in_bins = true;
|
||||||
|
// TODO: figure out better max_bins then this ...
|
||||||
|
int64_t max_bins = view.extent(0) / 2;
|
||||||
|
if (std::is_integral<typename ViewType::non_const_value_type>::value) {
|
||||||
|
// Cast to int64_t to avoid possible overflow when using integer
|
||||||
|
int64_t const max_val = result.max_val;
|
||||||
|
int64_t const min_val = result.min_val;
|
||||||
|
// using 10M as the cutoff for special behavior (roughly 40MB for the count
|
||||||
|
// array)
|
||||||
|
if ((max_val - min_val) < 10000000) {
|
||||||
|
max_bins = max_val - min_val + 1;
|
||||||
|
sort_in_bins = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BinSort<ViewType, CompType> bin_sort(
|
BinSort<ViewType, CompType> bin_sort(
|
||||||
view, CompType(view.extent(0) / 2, result.min_val, result.max_val), true);
|
view, CompType(max_bins, result.min_val, result.max_val), sort_in_bins);
|
||||||
bin_sort.create_permute_vector(exec);
|
bin_sort.create_permute_vector(exec);
|
||||||
bin_sort.sort(exec, view);
|
bin_sort.sort(exec, view);
|
||||||
}
|
}
|
||||||
|
|||||||
102
lib/kokkos/algorithms/src/Kokkos_StdAlgorithms.hpp
Normal file
102
lib/kokkos/algorithms/src/Kokkos_StdAlgorithms.hpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_ALGORITHMS_HPP
|
||||||
|
#define KOKKOS_STD_ALGORITHMS_HPP
|
||||||
|
|
||||||
|
/// \file Kokkos_StdAlgorithms.hpp
|
||||||
|
/// \brief Kokkos counterparts for Standard C++ Library algorithms
|
||||||
|
|
||||||
|
#include <std_algorithms/Kokkos_Constraints.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_RandomAccessIterator.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
|
||||||
|
// distance
|
||||||
|
#include <std_algorithms/Kokkos_Distance.hpp>
|
||||||
|
|
||||||
|
// move, swap, iter_swap
|
||||||
|
#include "std_algorithms/Kokkos_ModifyingOperations.hpp"
|
||||||
|
|
||||||
|
// find, find_if, find_if_not
|
||||||
|
// for_each, for_each_n
|
||||||
|
// mismatch
|
||||||
|
// equal
|
||||||
|
// count_if, count
|
||||||
|
// all_of, any_of, none_of
|
||||||
|
// adjacent_find
|
||||||
|
// lexicographical_compare
|
||||||
|
// search, search_n
|
||||||
|
// find_first_of, find_end
|
||||||
|
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||||
|
|
||||||
|
// replace, replace_copy_if, replace_copy, replace_if
|
||||||
|
// copy, copy_n, copy_backward, copy_if
|
||||||
|
// fill, fill_n
|
||||||
|
// transform
|
||||||
|
// generate, generate_n
|
||||||
|
// reverse, reverse_copy
|
||||||
|
// move, move_backward
|
||||||
|
// swap_ranges
|
||||||
|
// unique, unique_copy
|
||||||
|
// rotate, rotate_copy
|
||||||
|
// remove, remove_if, remove_copy, remove_copy_if
|
||||||
|
// shift_left, shift_right
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
|
||||||
|
// is_sorted_until, is_sorted
|
||||||
|
#include <std_algorithms/Kokkos_SortingOperations.hpp>
|
||||||
|
|
||||||
|
// min_element, max_element, minmax_element
|
||||||
|
#include <std_algorithms/Kokkos_MinMaxElementOperations.hpp>
|
||||||
|
|
||||||
|
// is_partitioned, partition_copy, partition_point
|
||||||
|
#include <std_algorithms/Kokkos_PartitioningOperations.hpp>
|
||||||
|
|
||||||
|
// adjacent_difference
|
||||||
|
// reduce, transform_reduce
|
||||||
|
// exclusive_scan, transform_exclusive_scan
|
||||||
|
// inclusive_scan, transform_inclusive_scan
|
||||||
|
#include <std_algorithms/Kokkos_Numeric.hpp>
|
||||||
|
|
||||||
|
#endif
|
||||||
105
lib/kokkos/algorithms/src/std_algorithms/Kokkos_BeginEnd.hpp
Normal file
105
lib/kokkos/algorithms/src/std_algorithms/Kokkos_BeginEnd.hpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_BEGIN_END_HPP
|
||||||
|
#define KOKKOS_BEGIN_END_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_View.hpp>
|
||||||
|
#include "Kokkos_RandomAccessIterator.hpp"
|
||||||
|
#include "Kokkos_Constraints.hpp"
|
||||||
|
|
||||||
|
/// \file Kokkos_BeginEnd.hpp
|
||||||
|
/// \brief Kokkos begin, end, cbegin, cend
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
|
||||||
|
template <class DataType, class... Properties>
|
||||||
|
KOKKOS_INLINE_FUNCTION auto begin(
|
||||||
|
const Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
using it_t =
|
||||||
|
Impl::RandomAccessIterator<Kokkos::View<DataType, Properties...>>;
|
||||||
|
return it_t(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class DataType, class... Properties>
|
||||||
|
KOKKOS_INLINE_FUNCTION auto end(
|
||||||
|
const Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
using it_t =
|
||||||
|
Impl::RandomAccessIterator<Kokkos::View<DataType, Properties...>>;
|
||||||
|
return it_t(v, v.extent(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class DataType, class... Properties>
|
||||||
|
KOKKOS_INLINE_FUNCTION auto cbegin(
|
||||||
|
const Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
using ViewConstType =
|
||||||
|
typename Kokkos::View<DataType, Properties...>::const_type;
|
||||||
|
const ViewConstType cv = v;
|
||||||
|
using it_t = Impl::RandomAccessIterator<ViewConstType>;
|
||||||
|
return it_t(cv);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class DataType, class... Properties>
|
||||||
|
KOKKOS_INLINE_FUNCTION auto cend(
|
||||||
|
const Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
using ViewConstType =
|
||||||
|
typename Kokkos::View<DataType, Properties...>::const_type;
|
||||||
|
const ViewConstType cv = v;
|
||||||
|
using it_t = Impl::RandomAccessIterator<ViewConstType>;
|
||||||
|
return it_t(cv, cv.extent(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
237
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Constraints.hpp
Normal file
237
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Constraints.hpp
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_ALGORITHMS_CONSTRAINTS_HPP_
|
||||||
|
#define KOKKOS_STD_ALGORITHMS_CONSTRAINTS_HPP_
|
||||||
|
|
||||||
|
#include <Kokkos_DetectionIdiom.hpp>
|
||||||
|
#include <Kokkos_View.hpp>
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
template <typename T, typename enable = void>
|
||||||
|
struct is_admissible_to_kokkos_std_algorithms : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_admissible_to_kokkos_std_algorithms<
|
||||||
|
T, std::enable_if_t< ::Kokkos::is_view<T>::value && T::rank == 1 &&
|
||||||
|
(std::is_same<typename T::traits::array_layout,
|
||||||
|
Kokkos::LayoutLeft>::value ||
|
||||||
|
std::is_same<typename T::traits::array_layout,
|
||||||
|
Kokkos::LayoutRight>::value ||
|
||||||
|
std::is_same<typename T::traits::array_layout,
|
||||||
|
Kokkos::LayoutStride>::value)> >
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
KOKKOS_INLINE_FUNCTION constexpr void
|
||||||
|
static_assert_is_admissible_to_kokkos_std_algorithms(
|
||||||
|
const ViewType& /* view */) {
|
||||||
|
static_assert(is_admissible_to_kokkos_std_algorithms<ViewType>::value,
|
||||||
|
"Currently, Kokkos standard algorithms only accept 1D Views.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// is_iterator
|
||||||
|
//
|
||||||
|
template <class T>
|
||||||
|
using iterator_category_t = typename T::iterator_category;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
using is_iterator = Kokkos::is_detected<iterator_category_t, T>;
|
||||||
|
|
||||||
|
//
|
||||||
|
// are_iterators
|
||||||
|
//
|
||||||
|
template <class... Args>
|
||||||
|
struct are_iterators;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct are_iterators<T> {
|
||||||
|
static constexpr bool value = is_iterator<T>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Head, class... Tail>
|
||||||
|
struct are_iterators<Head, Tail...> {
|
||||||
|
static constexpr bool value =
|
||||||
|
are_iterators<Head>::value && are_iterators<Tail...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// are_random_access_iterators
|
||||||
|
//
|
||||||
|
template <class... Args>
|
||||||
|
struct are_random_access_iterators;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct are_random_access_iterators<T> {
|
||||||
|
static constexpr bool value =
|
||||||
|
is_iterator<T>::value &&
|
||||||
|
std::is_base_of<std::random_access_iterator_tag,
|
||||||
|
typename T::iterator_category>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Head, class... Tail>
|
||||||
|
struct are_random_access_iterators<Head, Tail...> {
|
||||||
|
static constexpr bool value = are_random_access_iterators<Head>::value &&
|
||||||
|
are_random_access_iterators<Tail...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// iterators_are_accessible_from
|
||||||
|
//
|
||||||
|
template <class... Args>
|
||||||
|
struct iterators_are_accessible_from;
|
||||||
|
|
||||||
|
template <class ExeSpace, class IteratorType>
|
||||||
|
struct iterators_are_accessible_from<ExeSpace, IteratorType> {
|
||||||
|
using view_type = typename IteratorType::view_type;
|
||||||
|
static constexpr bool value =
|
||||||
|
SpaceAccessibility<ExeSpace,
|
||||||
|
typename view_type::memory_space>::accessible;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ExeSpace, class Head, class... Tail>
|
||||||
|
struct iterators_are_accessible_from<ExeSpace, Head, Tail...> {
|
||||||
|
static constexpr bool value =
|
||||||
|
iterators_are_accessible_from<ExeSpace, Head>::value &&
|
||||||
|
iterators_are_accessible_from<ExeSpace, Tail...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class... IteratorTypes>
|
||||||
|
KOKKOS_INLINE_FUNCTION constexpr void
|
||||||
|
static_assert_random_access_and_accessible(const ExecutionSpace& /* ex */,
|
||||||
|
IteratorTypes... /* iterators */) {
|
||||||
|
static_assert(
|
||||||
|
are_random_access_iterators<IteratorTypes...>::value,
|
||||||
|
"Currently, Kokkos standard algorithms require random access iterators.");
|
||||||
|
static_assert(
|
||||||
|
iterators_are_accessible_from<ExecutionSpace, IteratorTypes...>::value,
|
||||||
|
"Incompatible view/iterator and execution space");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// have matching difference_type
|
||||||
|
//
|
||||||
|
template <class... Args>
|
||||||
|
struct iterators_have_matching_difference_type;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct iterators_have_matching_difference_type<T> {
|
||||||
|
static constexpr bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T1, class T2>
|
||||||
|
struct iterators_have_matching_difference_type<T1, T2> {
|
||||||
|
static constexpr bool value =
|
||||||
|
std::is_same<typename T1::difference_type,
|
||||||
|
typename T2::difference_type>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T1, class T2, class... Tail>
|
||||||
|
struct iterators_have_matching_difference_type<T1, T2, Tail...> {
|
||||||
|
static constexpr bool value =
|
||||||
|
iterators_have_matching_difference_type<T1, T2>::value &&
|
||||||
|
iterators_have_matching_difference_type<T2, Tail...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IteratorType1, class IteratorType2>
|
||||||
|
KOKKOS_INLINE_FUNCTION constexpr void
|
||||||
|
static_assert_iterators_have_matching_difference_type(IteratorType1 /* it1 */,
|
||||||
|
IteratorType2 /* it2 */) {
|
||||||
|
static_assert(iterators_have_matching_difference_type<IteratorType1,
|
||||||
|
IteratorType2>::value,
|
||||||
|
"Iterators do not have matching difference_type");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class IteratorType1, class IteratorType2, class IteratorType3>
|
||||||
|
KOKKOS_INLINE_FUNCTION constexpr void
|
||||||
|
static_assert_iterators_have_matching_difference_type(IteratorType1 it1,
|
||||||
|
IteratorType2 it2,
|
||||||
|
IteratorType3 it3) {
|
||||||
|
static_assert_iterators_have_matching_difference_type(it1, it2);
|
||||||
|
static_assert_iterators_have_matching_difference_type(it2, it3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// not_openmptarget
|
||||||
|
//
|
||||||
|
template <class ExeSpace>
|
||||||
|
struct not_openmptarget {
|
||||||
|
#ifndef KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
static constexpr bool value = true;
|
||||||
|
#else
|
||||||
|
static constexpr bool value =
|
||||||
|
!std::is_same<std::decay_t<ExeSpace>,
|
||||||
|
::Kokkos::Experimental::OpenMPTarget>::value;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ExecutionSpace>
|
||||||
|
KOKKOS_INLINE_FUNCTION constexpr void static_assert_is_not_openmptarget(
|
||||||
|
const ExecutionSpace&) {
|
||||||
|
static_assert(not_openmptarget<ExecutionSpace>::value,
|
||||||
|
"Currently, Kokkos standard algorithms do not support custom "
|
||||||
|
"comparators in OpenMPTarget");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// valid range
|
||||||
|
//
|
||||||
|
template <class IteratorType>
|
||||||
|
void expect_valid_range(IteratorType first, IteratorType last) {
|
||||||
|
// this is a no-op for release
|
||||||
|
KOKKOS_EXPECTS(last >= first);
|
||||||
|
// avoid compiler complaining when KOKKOS_EXPECTS is no-op
|
||||||
|
(void)first;
|
||||||
|
(void)last;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Impl
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
69
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Distance.hpp
Normal file
69
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Distance.hpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_ALGORITHMS_DISTANCE_HPP
|
||||||
|
#define KOKKOS_STD_ALGORITHMS_DISTANCE_HPP
|
||||||
|
|
||||||
|
#include "Kokkos_Constraints.hpp"
|
||||||
|
#include "Kokkos_RandomAccessIterator.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
|
||||||
|
template <class IteratorType>
|
||||||
|
KOKKOS_INLINE_FUNCTION constexpr typename IteratorType::difference_type
|
||||||
|
distance(IteratorType first, IteratorType last) {
|
||||||
|
static_assert(
|
||||||
|
::Kokkos::Experimental::Impl::are_random_access_iterators<
|
||||||
|
IteratorType>::value,
|
||||||
|
"Kokkos::Experimental::distance: only implemented for random access "
|
||||||
|
"iterators.");
|
||||||
|
|
||||||
|
return last - first;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_HELPER_PREDICATES_HPP
|
||||||
|
#define KOKKOS_STD_HELPER_PREDICATES_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Macros.hpp>
|
||||||
|
|
||||||
|
// naming convetion:
|
||||||
|
// StdAlgoSomeExpressiveNameUnaryPredicate
|
||||||
|
// StdAlgoSomeExpressiveNameBinaryPredicate
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
// ------------------
|
||||||
|
// UNARY PREDICATES
|
||||||
|
// ------------------
|
||||||
|
template <class T>
|
||||||
|
struct StdAlgoEqualsValUnaryPredicate {
|
||||||
|
T m_value;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr bool operator()(const T& val) const { return val == m_value; }
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr explicit StdAlgoEqualsValUnaryPredicate(const T& _value)
|
||||||
|
: m_value(_value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct StdAlgoNotEqualsValUnaryPredicate {
|
||||||
|
T m_value;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr bool operator()(const T& val) const { return !(val == m_value); }
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr explicit StdAlgoNotEqualsValUnaryPredicate(const T& _value)
|
||||||
|
: m_value(_value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType, class PredicateType>
|
||||||
|
struct StdAlgoNegateUnaryPredicateWrapper {
|
||||||
|
PredicateType m_pred;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr bool operator()(const ValueType& val) const { return !m_pred(val); }
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr explicit StdAlgoNegateUnaryPredicateWrapper(
|
||||||
|
const PredicateType& pred)
|
||||||
|
: m_pred(pred) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------
|
||||||
|
// BINARY PREDICATES
|
||||||
|
// ------------------
|
||||||
|
template <class ValueType1, class ValueType2 = ValueType1>
|
||||||
|
struct StdAlgoEqualBinaryPredicate {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr bool operator()(const ValueType1& a, const ValueType2& b) const {
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType1, class ValueType2 = ValueType1>
|
||||||
|
struct StdAlgoLessThanBinaryPredicate {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr bool operator()(const ValueType1& a, const ValueType2& b) const {
|
||||||
|
return a < b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Impl
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
#endif
|
||||||
@ -0,0 +1,409 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_MIN_MAX_ELEMENT_OPERATIONS_HPP
|
||||||
|
#define KOKKOS_STD_MIN_MAX_ELEMENT_OPERATIONS_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "Kokkos_BeginEnd.hpp"
|
||||||
|
#include "Kokkos_Constraints.hpp"
|
||||||
|
#include "Kokkos_Distance.hpp"
|
||||||
|
#include "Kokkos_ModifyingOperations.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
template <class IteratorType, class ReducerType>
|
||||||
|
struct StdMinOrMaxElemFunctor {
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
|
||||||
|
IteratorType m_first;
|
||||||
|
ReducerType m_reducer;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i, red_value_type& red_value) const {
|
||||||
|
m_reducer.join(red_value, red_value_type{m_first[i], i});
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdMinOrMaxElemFunctor(IteratorType first, ReducerType reducer)
|
||||||
|
: m_first(std::move(first)), m_reducer(std::move(reducer)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IteratorType, class ReducerType>
|
||||||
|
struct StdMinMaxElemFunctor {
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
IteratorType m_first;
|
||||||
|
ReducerType m_reducer;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i, red_value_type& red_value) const {
|
||||||
|
const auto& my_value = m_first[i];
|
||||||
|
m_reducer.join(red_value, red_value_type{my_value, my_value, i, i});
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdMinMaxElemFunctor(IteratorType first, ReducerType reducer)
|
||||||
|
: m_first(std::move(first)), m_reducer(std::move(reducer)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// min_or_max_element_impl
|
||||||
|
// ------------------------------------------
|
||||||
|
template <template <class... Args> class ReducerType, class ExecutionSpace,
|
||||||
|
class IteratorType, class... Args>
|
||||||
|
IteratorType min_or_max_element_impl(const std::string& label,
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
Args&&... args) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||||
|
Impl::expect_valid_range(first, last);
|
||||||
|
|
||||||
|
if (first == last) {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
using value_type = typename IteratorType::value_type;
|
||||||
|
using reducer_type = ReducerType<value_type, index_type, Args...>;
|
||||||
|
using reduction_value_type = typename reducer_type::value_type;
|
||||||
|
using func_t = StdMinOrMaxElemFunctor<IteratorType, reducer_type>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
reduction_value_type red_result;
|
||||||
|
reducer_type reducer(red_result, std::forward<Args>(args)...);
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
::Kokkos::parallel_reduce(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_t(first, reducer), reducer);
|
||||||
|
|
||||||
|
// fence not needed because reducing into scalar
|
||||||
|
|
||||||
|
// return
|
||||||
|
return first + red_result.loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// minmax_element_impl
|
||||||
|
// ------------------------------------------
|
||||||
|
template <template <class... Args> class ReducerType, class ExecutionSpace,
|
||||||
|
class IteratorType, class... Args>
|
||||||
|
::Kokkos::pair<IteratorType, IteratorType> minmax_element_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, Args&&... args) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||||
|
Impl::expect_valid_range(first, last);
|
||||||
|
|
||||||
|
if (first == last) {
|
||||||
|
return {first, first};
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
using value_type = typename IteratorType::value_type;
|
||||||
|
using reducer_type = ReducerType<value_type, index_type, Args...>;
|
||||||
|
using reduction_value_type = typename reducer_type::value_type;
|
||||||
|
using func_t = StdMinMaxElemFunctor<IteratorType, reducer_type>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
reduction_value_type red_result;
|
||||||
|
reducer_type reducer(red_result, std::forward<Args>(args)...);
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
::Kokkos::parallel_reduce(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_t(first, reducer), reducer);
|
||||||
|
|
||||||
|
// fence not needed because reducing into scalar
|
||||||
|
|
||||||
|
// return
|
||||||
|
return {first + red_result.min_loc, first + red_result.max_loc};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Impl
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// min_element public API
|
||||||
|
// ----------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
auto min_element(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
return Impl::min_or_max_element_impl<MinFirstLoc>(
|
||||||
|
"Kokkos::min_element_iterator_api_default", ex, first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
auto min_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last) {
|
||||||
|
return Impl::min_or_max_element_impl<MinFirstLoc>(label, ex, first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
auto min_element(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MinFirstLocCustomComparator>(
|
||||||
|
"Kokkos::min_element_iterator_api_default", ex, first, last,
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
auto min_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last, ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MinFirstLocCustomComparator>(
|
||||||
|
label, ex, first, last, std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto min_element(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MinFirstLoc>(
|
||||||
|
"Kokkos::min_element_view_api_default", ex, begin(v), end(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||||
|
class... Properties>
|
||||||
|
auto min_element(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MinFirstLocCustomComparator>(
|
||||||
|
"Kokkos::min_element_view_api_default", ex, begin(v), end(v),
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto min_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MinFirstLoc>(label, ex, begin(v),
|
||||||
|
end(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||||
|
class... Properties>
|
||||||
|
auto min_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MinFirstLocCustomComparator>(
|
||||||
|
label, ex, begin(v), end(v), std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// max_element public API
|
||||||
|
// ----------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
auto max_element(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
return Impl::min_or_max_element_impl<MaxFirstLoc>(
|
||||||
|
"Kokkos::max_element_iterator_api_default", ex, first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
auto max_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last) {
|
||||||
|
return Impl::min_or_max_element_impl<MaxFirstLoc>(label, ex, first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
auto max_element(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MaxFirstLocCustomComparator>(
|
||||||
|
"Kokkos::max_element_iterator_api_default", ex, first, last,
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
auto max_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last, ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MaxFirstLocCustomComparator>(
|
||||||
|
label, ex, first, last, std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto max_element(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MaxFirstLoc>(
|
||||||
|
"Kokkos::max_element_view_api_default", ex, begin(v), end(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto max_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MaxFirstLoc>(label, ex, begin(v),
|
||||||
|
end(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||||
|
class... Properties>
|
||||||
|
auto max_element(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MaxFirstLocCustomComparator>(
|
||||||
|
"Kokkos::max_element_view_api_default", ex, begin(v), end(v),
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||||
|
class... Properties>
|
||||||
|
auto max_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::min_or_max_element_impl<MaxFirstLocCustomComparator>(
|
||||||
|
label, ex, begin(v), end(v), std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// minmax_element public API
|
||||||
|
// -------------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
auto minmax_element(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
return Impl::minmax_element_impl<MinMaxFirstLastLoc>(
|
||||||
|
"Kokkos::minmax_element_iterator_api_default", ex, first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
auto minmax_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last) {
|
||||||
|
return Impl::minmax_element_impl<MinMaxFirstLastLoc>(label, ex, first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
auto minmax_element(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::minmax_element_impl<MinMaxFirstLastLocCustomComparator>(
|
||||||
|
"Kokkos::minmax_element_iterator_api_default", ex, first, last,
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
auto minmax_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::minmax_element_impl<MinMaxFirstLastLocCustomComparator>(
|
||||||
|
label, ex, first, last, std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto minmax_element(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
return Impl::minmax_element_impl<MinMaxFirstLastLoc>(
|
||||||
|
"Kokkos::minmax_element_view_api_default", ex, begin(v), end(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto minmax_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
return Impl::minmax_element_impl<MinMaxFirstLastLoc>(label, ex, begin(v),
|
||||||
|
end(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||||
|
class... Properties>
|
||||||
|
auto minmax_element(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::minmax_element_impl<MinMaxFirstLastLocCustomComparator>(
|
||||||
|
"Kokkos::minmax_element_view_api_default", ex, begin(v), end(v),
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class ComparatorType,
|
||||||
|
class... Properties>
|
||||||
|
auto minmax_element(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::minmax_element_impl<MinMaxFirstLastLocCustomComparator>(
|
||||||
|
label, ex, begin(v), end(v), std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_MODIFYING_OPERATIONS_HPP
|
||||||
|
#define KOKKOS_MODIFYING_OPERATIONS_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "Kokkos_BeginEnd.hpp"
|
||||||
|
#include "Kokkos_Constraints.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
|
||||||
|
// move
|
||||||
|
template <typename T>
|
||||||
|
KOKKOS_INLINE_FUNCTION std::remove_reference_t<T>&& move(T&& t) {
|
||||||
|
return static_cast<std::remove_reference_t<T>&&>(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// swap
|
||||||
|
template <class T>
|
||||||
|
KOKKOS_INLINE_FUNCTION void swap(T& a, T& b) noexcept {
|
||||||
|
static_assert(
|
||||||
|
std::is_move_assignable<T>::value && std::is_move_constructible<T>::value,
|
||||||
|
"Kokkos::Experimental::swap arguments must be move assignable "
|
||||||
|
"and move constructible");
|
||||||
|
|
||||||
|
T tmp = std::move(a);
|
||||||
|
a = std::move(b);
|
||||||
|
b = std::move(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// this is here because we use the swap function above
|
||||||
|
namespace Impl {
|
||||||
|
template <class IteratorType1, class IteratorType2>
|
||||||
|
struct StdIterSwapFunctor {
|
||||||
|
IteratorType1 m_a;
|
||||||
|
IteratorType2 m_b;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(int i) const {
|
||||||
|
(void)i;
|
||||||
|
::Kokkos::Experimental::swap(*m_a, *m_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdIterSwapFunctor(IteratorType1 _a, IteratorType2 _b)
|
||||||
|
: m_a(std::move(_a)), m_b(std::move(_b)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IteratorType1, class IteratorType2>
|
||||||
|
void iter_swap_impl(IteratorType1 a, IteratorType2 b) {
|
||||||
|
// is there a better way to do this maybe?
|
||||||
|
::Kokkos::parallel_for(
|
||||||
|
1, StdIterSwapFunctor<IteratorType1, IteratorType2>(a, b));
|
||||||
|
Kokkos::DefaultExecutionSpace().fence(
|
||||||
|
"Kokkos::iter_swap: fence after operation");
|
||||||
|
}
|
||||||
|
} // namespace Impl
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// iter_swap
|
||||||
|
template <class IteratorType1, class IteratorType2>
|
||||||
|
void iter_swap(IteratorType1 a, IteratorType2 b) {
|
||||||
|
Impl::iter_swap_impl(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_MOD_SEQ_OPS_INC_ALL_HPP
|
||||||
|
#define KOKKOS_STD_MOD_SEQ_OPS_INC_ALL_HPP
|
||||||
|
|
||||||
|
#include "./modifying_sequence_ops/Kokkos_ModifyingSequenceOperationsSet1.hpp"
|
||||||
|
#include "./modifying_sequence_ops/Kokkos_ModifyingSequenceOperationsSet2.hpp"
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
59
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Numeric.hpp
Normal file
59
lib/kokkos/algorithms/src/std_algorithms/Kokkos_Numeric.hpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_NUMERIC_ALL_HPP
|
||||||
|
#define KOKKOS_STD_NUMERIC_ALL_HPP
|
||||||
|
|
||||||
|
#include "./numeric/Kokkos_AdjacentDifference.hpp"
|
||||||
|
|
||||||
|
// contains exclusive_scan, transform_exclusive_scan
|
||||||
|
#include "./numeric/Kokkos_ExclusiveScan.hpp"
|
||||||
|
|
||||||
|
// contains inclusive_scan, transform_inclusive_scan
|
||||||
|
#include "./numeric/Kokkos_InclusiveScan.hpp"
|
||||||
|
|
||||||
|
#include "./numeric/Kokkos_Reduce.hpp"
|
||||||
|
#include "./numeric/Kokkos_TransformReduce.hpp"
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,491 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_PARTITIONING_OPERATIONS_HPP
|
||||||
|
#define KOKKOS_STD_PARTITIONING_OPERATIONS_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "Kokkos_BeginEnd.hpp"
|
||||||
|
#include "Kokkos_Constraints.hpp"
|
||||||
|
#include "Kokkos_ModifyingOperations.hpp"
|
||||||
|
#include "Kokkos_NonModifyingSequenceOperations.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
//
|
||||||
|
// functors
|
||||||
|
//
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
template <class IteratorType, class ReducerType, class PredicateType>
|
||||||
|
struct StdIsPartitionedFunctor {
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
|
||||||
|
IteratorType m_first;
|
||||||
|
ReducerType m_reducer;
|
||||||
|
PredicateType m_p;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i, red_value_type& redValue) const {
|
||||||
|
const auto predicate_value = m_p(m_first[i]);
|
||||||
|
constexpr index_type m_red_id_min =
|
||||||
|
::Kokkos::reduction_identity<index_type>::min();
|
||||||
|
constexpr index_type m_red_id_max =
|
||||||
|
::Kokkos::reduction_identity<index_type>::max();
|
||||||
|
auto rv = predicate_value ? red_value_type{i, m_red_id_min}
|
||||||
|
: red_value_type{m_red_id_max, i};
|
||||||
|
|
||||||
|
m_reducer.join(redValue, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdIsPartitionedFunctor(IteratorType first, ReducerType reducer,
|
||||||
|
PredicateType p)
|
||||||
|
: m_first(std::move(first)),
|
||||||
|
m_reducer(std::move(reducer)),
|
||||||
|
m_p(std::move(p)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IteratorType, class ReducerType, class PredicateType>
|
||||||
|
struct StdPartitionPointFunctor {
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
|
||||||
|
IteratorType m_first;
|
||||||
|
ReducerType m_reducer;
|
||||||
|
PredicateType m_p;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i, red_value_type& redValue) const {
|
||||||
|
const auto predicate_value = m_p(m_first[i]);
|
||||||
|
auto rv =
|
||||||
|
predicate_value
|
||||||
|
? red_value_type{::Kokkos::reduction_identity<index_type>::min()}
|
||||||
|
: red_value_type{i};
|
||||||
|
m_reducer.join(redValue, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdPartitionPointFunctor(IteratorType first, ReducerType reducer,
|
||||||
|
PredicateType p)
|
||||||
|
: m_first(std::move(first)),
|
||||||
|
m_reducer(std::move(reducer)),
|
||||||
|
m_p(std::move(p)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct StdPartitionCopyScalar {
|
||||||
|
ValueType true_count_;
|
||||||
|
ValueType false_count_;
|
||||||
|
|
||||||
|
// Here we implement the copy assignment operators explicitly for consistency
|
||||||
|
// with how the Scalar structs are implemented inside
|
||||||
|
// Kokkos_Parallel_Reduce.hpp.
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator=(const StdPartitionCopyScalar& other) {
|
||||||
|
true_count_ = other.true_count_;
|
||||||
|
false_count_ = other.false_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator=(const volatile StdPartitionCopyScalar& other) volatile {
|
||||||
|
true_count_ = other.true_count_;
|
||||||
|
false_count_ = other.false_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is needed for
|
||||||
|
// OpenMPTarget/Kokkos_OpenMPTarget_Parallel.hpp:699:21: error: no viable
|
||||||
|
// overloaded '=' m_returnvalue = 0;
|
||||||
|
//
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator=(const ValueType value) {
|
||||||
|
true_count_ = value;
|
||||||
|
false_count_ = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IndexType, class FirstFrom, class FirstDestTrue,
|
||||||
|
class FirstDestFalse, class PredType>
|
||||||
|
struct StdPartitionCopyFunctor {
|
||||||
|
using value_type = StdPartitionCopyScalar<IndexType>;
|
||||||
|
|
||||||
|
FirstFrom m_first_from;
|
||||||
|
FirstDestTrue m_first_dest_true;
|
||||||
|
FirstDestFalse m_first_dest_false;
|
||||||
|
PredType m_pred;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdPartitionCopyFunctor(FirstFrom first_from, FirstDestTrue first_dest_true,
|
||||||
|
FirstDestFalse first_dest_false, PredType pred)
|
||||||
|
: m_first_from(std::move(first_from)),
|
||||||
|
m_first_dest_true(std::move(first_dest_true)),
|
||||||
|
m_first_dest_false(std::move(first_dest_false)),
|
||||||
|
m_pred(std::move(pred)) {}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const IndexType i, value_type& update,
|
||||||
|
const bool final_pass) const {
|
||||||
|
const auto& myval = m_first_from[i];
|
||||||
|
if (final_pass) {
|
||||||
|
if (m_pred(myval)) {
|
||||||
|
m_first_dest_true[update.true_count_] = myval;
|
||||||
|
} else {
|
||||||
|
m_first_dest_false[update.false_count_] = myval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_pred(myval)) {
|
||||||
|
update.true_count_ += 1;
|
||||||
|
} else {
|
||||||
|
update.false_count_ += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void init(value_type& update) const {
|
||||||
|
update.true_count_ = 0;
|
||||||
|
update.false_count_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void join(volatile value_type& update,
|
||||||
|
volatile const value_type& input) const {
|
||||||
|
update.true_count_ += input.true_count_;
|
||||||
|
update.false_count_ += input.false_count_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// is_partitioned_impl
|
||||||
|
// ------------------------------------------
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class PredicateType>
|
||||||
|
bool is_partitioned_impl(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
PredicateType pred) {
|
||||||
|
// true if all elements in the range [first, last) that satisfy
|
||||||
|
// the predicate "pred" appear before all elements that don't.
|
||||||
|
// Also returns true if [first, last) is empty.
|
||||||
|
// also true if all elements satisfy the predicate.
|
||||||
|
|
||||||
|
// we implement it by finding:
|
||||||
|
// - the max location where predicate is true (max_loc_true)
|
||||||
|
// - the min location where predicate is false (min_loc_false)
|
||||||
|
// so the range is partitioned if max_loc_true < (min_loc_false)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||||
|
Impl::expect_valid_range(first, last);
|
||||||
|
|
||||||
|
// trivial case
|
||||||
|
if (first == last) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
using reducer_type = StdIsPartitioned<index_type>;
|
||||||
|
using reduction_value_type = typename reducer_type::value_type;
|
||||||
|
using func_t =
|
||||||
|
StdIsPartitionedFunctor<IteratorType, reducer_type, PredicateType>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
reduction_value_type red_result;
|
||||||
|
reducer_type reducer(red_result);
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
::Kokkos::parallel_reduce(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_t(first, reducer, pred), reducer);
|
||||||
|
|
||||||
|
// fence not needed because reducing into scalar
|
||||||
|
|
||||||
|
// decide and return
|
||||||
|
constexpr index_type red_id_min =
|
||||||
|
::Kokkos::reduction_identity<index_type>::min();
|
||||||
|
constexpr index_type red_id_max =
|
||||||
|
::Kokkos::reduction_identity<index_type>::max();
|
||||||
|
|
||||||
|
if (red_result.max_loc_true != red_id_max &&
|
||||||
|
red_result.min_loc_false != red_id_min) {
|
||||||
|
return red_result.max_loc_true < red_result.min_loc_false;
|
||||||
|
} else if (first + red_result.max_loc_true == --last) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// partition_point_impl
|
||||||
|
// ------------------------------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType, class PredicateType>
|
||||||
|
IteratorType partition_point_impl(const std::string& label,
|
||||||
|
const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, PredicateType pred) {
|
||||||
|
// locates the end of the first partition, that is, the first
|
||||||
|
// element that does not satisfy p or last if all elements satisfy p.
|
||||||
|
// Implementation below finds the first location where p is false.
|
||||||
|
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||||
|
Impl::expect_valid_range(first, last);
|
||||||
|
|
||||||
|
if (first == last) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
using reducer_type = StdPartitionPoint<index_type>;
|
||||||
|
using reduction_value_type = typename reducer_type::value_type;
|
||||||
|
using func_t =
|
||||||
|
StdPartitionPointFunctor<IteratorType, reducer_type, PredicateType>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
reduction_value_type red_result;
|
||||||
|
reducer_type reducer(red_result);
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
::Kokkos::parallel_reduce(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_t(first, reducer, pred), reducer);
|
||||||
|
|
||||||
|
// fence not needed because reducing into scalar
|
||||||
|
|
||||||
|
// decide and return
|
||||||
|
if (red_result.min_loc_false ==
|
||||||
|
::Kokkos::reduction_identity<index_type>::min()) {
|
||||||
|
// if all elements are true, return last
|
||||||
|
return last;
|
||||||
|
} else {
|
||||||
|
return first + red_result.min_loc_false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// partition_copy_impl
|
||||||
|
// ------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorTrueType, class OutputIteratorFalseType,
|
||||||
|
class PredicateType>
|
||||||
|
::Kokkos::pair<OutputIteratorTrueType, OutputIteratorFalseType>
|
||||||
|
partition_copy_impl(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType from_first, InputIteratorType from_last,
|
||||||
|
OutputIteratorTrueType to_first_true,
|
||||||
|
OutputIteratorFalseType to_first_false,
|
||||||
|
PredicateType pred) {
|
||||||
|
// impl uses a scan, this is similar how we implemented copy_if
|
||||||
|
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(
|
||||||
|
ex, from_first, to_first_true, to_first_false);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(
|
||||||
|
from_first, to_first_true, to_first_false);
|
||||||
|
Impl::expect_valid_range(from_first, from_last);
|
||||||
|
|
||||||
|
if (from_first == from_last) {
|
||||||
|
return {to_first_true, to_first_false};
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
using func_type =
|
||||||
|
StdPartitionCopyFunctor<index_type, InputIteratorType,
|
||||||
|
OutputIteratorTrueType, OutputIteratorFalseType,
|
||||||
|
PredicateType>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(from_first, from_last);
|
||||||
|
typename func_type::value_type counts{0, 0};
|
||||||
|
::Kokkos::parallel_scan(
|
||||||
|
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_type(from_first, to_first_true, to_first_false, pred), counts);
|
||||||
|
|
||||||
|
// fence not needed here because of the scan into counts
|
||||||
|
|
||||||
|
return {to_first_true + counts.true_count_,
|
||||||
|
to_first_false + counts.false_count_};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Impl
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// is_partitioned public API
|
||||||
|
// ----------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType, class PredicateType>
|
||||||
|
bool is_partitioned(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, PredicateType p) {
|
||||||
|
return Impl::is_partitioned_impl(
|
||||||
|
"Kokkos::is_partitioned_iterator_api_default", ex, first, last,
|
||||||
|
std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class PredicateType>
|
||||||
|
bool is_partitioned(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last, PredicateType p) {
|
||||||
|
return Impl::is_partitioned_impl(label, ex, first, last, std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class PredicateType, class DataType,
|
||||||
|
class... Properties>
|
||||||
|
bool is_partitioned(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
PredicateType p) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
return Impl::is_partitioned_impl("Kokkos::is_partitioned_view_api_default",
|
||||||
|
ex, cbegin(v), cend(v), std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class PredicateType, class DataType,
|
||||||
|
class... Properties>
|
||||||
|
bool is_partitioned(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
PredicateType p) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
|
||||||
|
return Impl::is_partitioned_impl(label, ex, cbegin(v), cend(v), std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// partition_copy
|
||||||
|
// ----------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorTrueType, class OutputIteratorFalseType,
|
||||||
|
class PredicateType>
|
||||||
|
::Kokkos::pair<OutputIteratorTrueType, OutputIteratorFalseType> partition_copy(
|
||||||
|
const ExecutionSpace& ex, InputIteratorType from_first,
|
||||||
|
InputIteratorType from_last, OutputIteratorTrueType to_first_true,
|
||||||
|
OutputIteratorFalseType to_first_false, PredicateType p) {
|
||||||
|
return Impl::partition_copy_impl(
|
||||||
|
"Kokkos::partition_copy_iterator_api_default", ex, from_first, from_last,
|
||||||
|
to_first_true, to_first_false, std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorTrueType, class OutputIteratorFalseType,
|
||||||
|
class PredicateType>
|
||||||
|
::Kokkos::pair<OutputIteratorTrueType, OutputIteratorFalseType> partition_copy(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType from_first, InputIteratorType from_last,
|
||||||
|
OutputIteratorTrueType to_first_true,
|
||||||
|
OutputIteratorFalseType to_first_false, PredicateType p) {
|
||||||
|
return Impl::partition_copy_impl(label, ex, from_first, from_last,
|
||||||
|
to_first_true, to_first_false, std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class DataType3,
|
||||||
|
class... Properties3, class PredicateType>
|
||||||
|
auto partition_copy(
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest_true,
|
||||||
|
const ::Kokkos::View<DataType3, Properties3...>& view_dest_false,
|
||||||
|
PredicateType p) {
|
||||||
|
return Impl::partition_copy_impl("Kokkos::partition_copy_view_api_default",
|
||||||
|
ex, cbegin(view_from), cend(view_from),
|
||||||
|
begin(view_dest_true),
|
||||||
|
begin(view_dest_false), std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class DataType3,
|
||||||
|
class... Properties3, class PredicateType>
|
||||||
|
auto partition_copy(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest_true,
|
||||||
|
const ::Kokkos::View<DataType3, Properties3...>& view_dest_false,
|
||||||
|
PredicateType p) {
|
||||||
|
return Impl::partition_copy_impl(label, ex, cbegin(view_from),
|
||||||
|
cend(view_from), begin(view_dest_true),
|
||||||
|
begin(view_dest_false), std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// partition_point
|
||||||
|
// ----------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType, class UnaryPredicate>
|
||||||
|
IteratorType partition_point(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, UnaryPredicate p) {
|
||||||
|
return Impl::partition_point_impl(
|
||||||
|
"Kokkos::partitioned_point_iterator_api_default", ex, first, last,
|
||||||
|
std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class UnaryPredicate>
|
||||||
|
IteratorType partition_point(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
UnaryPredicate p) {
|
||||||
|
return Impl::partition_point_impl(label, ex, first, last, std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class UnaryPredicate, class DataType,
|
||||||
|
class... Properties>
|
||||||
|
auto partition_point(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
UnaryPredicate p) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
return Impl::partition_point_impl(label, ex, begin(v), end(v), std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class UnaryPredicate, class DataType,
|
||||||
|
class... Properties>
|
||||||
|
auto partition_point(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& v,
|
||||||
|
UnaryPredicate p) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(v);
|
||||||
|
return Impl::partition_point_impl("Kokkos::partition_point_view_api_default",
|
||||||
|
ex, begin(v), end(v), std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_RANDOM_ACCESS_ITERATOR_HPP
|
||||||
|
#define KOKKOS_RANDOM_ACCESS_ITERATOR_HPP
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <Kokkos_Macros.hpp>
|
||||||
|
#include <Kokkos_View.hpp>
|
||||||
|
#include "Kokkos_Constraints.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class RandomAccessIterator;
|
||||||
|
|
||||||
|
template <class DataType, class... Args>
|
||||||
|
class RandomAccessIterator< ::Kokkos::View<DataType, Args...> >
|
||||||
|
: public std::iterator<
|
||||||
|
std::random_access_iterator_tag,
|
||||||
|
typename ::Kokkos::View<DataType, Args...>::value_type, ptrdiff_t,
|
||||||
|
typename ::Kokkos::View<DataType, Args...>::pointer_type,
|
||||||
|
typename ::Kokkos::View<DataType, Args...>::reference_type> {
|
||||||
|
public:
|
||||||
|
using view_type = ::Kokkos::View<DataType, Args...>;
|
||||||
|
using iterator_type = RandomAccessIterator<view_type>;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
using value_type = typename view_type::value_type;
|
||||||
|
using reference = typename view_type::reference_type;
|
||||||
|
|
||||||
|
static_assert(view_type::rank == 1 &&
|
||||||
|
(std::is_same<typename view_type::traits::array_layout,
|
||||||
|
Kokkos::LayoutLeft>::value ||
|
||||||
|
std::is_same<typename view_type::traits::array_layout,
|
||||||
|
Kokkos::LayoutRight>::value ||
|
||||||
|
std::is_same<typename view_type::traits::array_layout,
|
||||||
|
Kokkos::LayoutStride>::value),
|
||||||
|
"RandomAccessIterator only supports 1D Views with LayoutLeft, "
|
||||||
|
"LayoutRight, LayoutStride.");
|
||||||
|
|
||||||
|
KOKKOS_DEFAULTED_FUNCTION RandomAccessIterator() = default;
|
||||||
|
|
||||||
|
explicit KOKKOS_FUNCTION RandomAccessIterator(const view_type view)
|
||||||
|
: m_view(view) {}
|
||||||
|
explicit KOKKOS_FUNCTION RandomAccessIterator(const view_type view,
|
||||||
|
ptrdiff_t current_index)
|
||||||
|
: m_view(view), m_current_index(current_index) {}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
iterator_type& operator++() {
|
||||||
|
++m_current_index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
iterator_type operator++(int) {
|
||||||
|
auto tmp = *this;
|
||||||
|
++*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
iterator_type& operator--() {
|
||||||
|
--m_current_index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
iterator_type operator--(int) {
|
||||||
|
auto tmp = *this;
|
||||||
|
--*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
reference operator[](difference_type n) const {
|
||||||
|
return m_view(m_current_index + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
iterator_type& operator+=(difference_type n) {
|
||||||
|
m_current_index += n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
iterator_type& operator-=(difference_type n) {
|
||||||
|
m_current_index -= n;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
iterator_type operator+(difference_type n) const {
|
||||||
|
return iterator_type(m_view, m_current_index + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
iterator_type operator-(difference_type n) const {
|
||||||
|
return iterator_type(m_view, m_current_index - n);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
difference_type operator-(iterator_type it) const {
|
||||||
|
return m_current_index - it.m_current_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
bool operator==(iterator_type other) const {
|
||||||
|
return m_current_index == other.m_current_index &&
|
||||||
|
m_view.data() == other.m_view.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
bool operator!=(iterator_type other) const {
|
||||||
|
return m_current_index != other.m_current_index ||
|
||||||
|
m_view.data() != other.m_view.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
bool operator<(iterator_type other) const {
|
||||||
|
return m_current_index < other.m_current_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
bool operator<=(iterator_type other) const {
|
||||||
|
return m_current_index <= other.m_current_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
bool operator>(iterator_type other) const {
|
||||||
|
return m_current_index > other.m_current_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
bool operator>=(iterator_type other) const {
|
||||||
|
return m_current_index >= other.m_current_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
reference operator*() const { return m_view(m_current_index); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
view_type m_view;
|
||||||
|
ptrdiff_t m_current_index = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Impl
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_ReducerWithArbitraryJoinerNoNeutralElement_hpp_
|
||||||
|
#define KOKKOS_STD_ReducerWithArbitraryJoinerNoNeutralElement_hpp_
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "Kokkos_ValueWrapperForNoNeutralElement.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
// This reducer is here and not where all other reducers are
|
||||||
|
// because it is inside Impl and also because it would not work
|
||||||
|
// for OpenMPTarget backend. We can move this later.
|
||||||
|
|
||||||
|
template <class Scalar, class JoinerType, class Space = HostSpace>
|
||||||
|
struct ReducerWithArbitraryJoinerNoNeutralElement {
|
||||||
|
using scalar_type = typename std::remove_cv<Scalar>::type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Required
|
||||||
|
using reducer =
|
||||||
|
ReducerWithArbitraryJoinerNoNeutralElement<Scalar, JoinerType, Space>;
|
||||||
|
using value_type = ValueWrapperForNoNeutralElement<scalar_type>;
|
||||||
|
|
||||||
|
using result_view_type = Kokkos::View<value_type, Space>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
JoinerType m_joiner;
|
||||||
|
result_view_type m_value;
|
||||||
|
bool m_references_scalar_v;
|
||||||
|
|
||||||
|
public:
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
ReducerWithArbitraryJoinerNoNeutralElement(value_type& value_,
|
||||||
|
JoinerType joiner_)
|
||||||
|
: m_joiner(joiner_), m_value(&value_), m_references_scalar_v(true) {}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
ReducerWithArbitraryJoinerNoNeutralElement(const result_view_type& value_,
|
||||||
|
JoinerType joiner_)
|
||||||
|
: m_joiner(joiner_), m_value(value_), m_references_scalar_v(false) {}
|
||||||
|
|
||||||
|
// Required
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void join(value_type& dest, const value_type& src) const {
|
||||||
|
dest.val = m_joiner(dest.val, src.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void join(volatile value_type& dest, const volatile value_type& src) const {
|
||||||
|
dest.val = m_joiner(dest.val, src.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void init(value_type& val) const {
|
||||||
|
// I cannot call reduction_identity, so need to default this
|
||||||
|
val = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
value_type& reference() const { return *m_value.data(); }
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
result_view_type view() const { return m_value; }
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
bool references_scalar() const { return m_references_scalar_v; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Impl
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,378 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_SORTING_OPERATIONS_HPP
|
||||||
|
#define KOKKOS_STD_SORTING_OPERATIONS_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "Kokkos_BeginEnd.hpp"
|
||||||
|
#include "Kokkos_Constraints.hpp"
|
||||||
|
#include "Kokkos_NonModifyingSequenceOperations.hpp"
|
||||||
|
#include "Kokkos_HelperPredicates.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
// ------------------
|
||||||
|
//
|
||||||
|
// functors
|
||||||
|
//
|
||||||
|
// ------------------
|
||||||
|
|
||||||
|
template <class IteratorType, class IndicatorViewType, class ComparatorType>
|
||||||
|
struct StdIsSortedUntilFunctor {
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
IteratorType m_first;
|
||||||
|
IndicatorViewType m_indicator;
|
||||||
|
ComparatorType m_comparator;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i, int& update, const bool final) const {
|
||||||
|
const auto& val_i = m_first[i];
|
||||||
|
const auto& val_ip1 = m_first[i + 1];
|
||||||
|
|
||||||
|
if (m_comparator(val_ip1, val_i)) {
|
||||||
|
++update;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (final) {
|
||||||
|
m_indicator(i) = update;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdIsSortedUntilFunctor(IteratorType _first1, IndicatorViewType indicator,
|
||||||
|
ComparatorType comparator)
|
||||||
|
: m_first(std::move(_first1)),
|
||||||
|
m_indicator(std::move(indicator)),
|
||||||
|
m_comparator(std::move(comparator)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IteratorType, class ComparatorType>
|
||||||
|
struct StdIsSortedFunctor {
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
IteratorType m_first;
|
||||||
|
ComparatorType m_comparator;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i, std::size_t& update) const {
|
||||||
|
const auto& val_i = m_first[i];
|
||||||
|
const auto& val_ip1 = m_first[i + 1];
|
||||||
|
|
||||||
|
if (m_comparator(val_ip1, val_i)) {
|
||||||
|
++update;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdIsSortedFunctor(IteratorType _first1, ComparatorType comparator)
|
||||||
|
: m_first(std::move(_first1)), m_comparator(std::move(comparator)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// is_sorted_until_impl
|
||||||
|
// ------------------------------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
IteratorType is_sorted_until_impl(const std::string& label,
|
||||||
|
const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, ComparatorType comp) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||||
|
Impl::expect_valid_range(first, last);
|
||||||
|
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
|
||||||
|
// trivial case
|
||||||
|
if (num_elements <= 1) {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
use scan and a helper "indicator" view
|
||||||
|
such that we scan the data and fill the indicator with
|
||||||
|
partial sum that is always 0 unless we find a pair that
|
||||||
|
breaks the sorting, so in that case the indicator will
|
||||||
|
have a 1 starting at the location where the sorting breaks.
|
||||||
|
So finding that 1 means finding the location we want.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using indicator_value_type = std::size_t;
|
||||||
|
using indicator_view_type =
|
||||||
|
::Kokkos::View<indicator_value_type*, ExecutionSpace>;
|
||||||
|
using functor_type =
|
||||||
|
StdIsSortedUntilFunctor<IteratorType, indicator_view_type,
|
||||||
|
ComparatorType>;
|
||||||
|
|
||||||
|
// do scan
|
||||||
|
// use num_elements-1 because each index handles i and i+1
|
||||||
|
const auto num_elements_minus_one = num_elements - 1;
|
||||||
|
indicator_view_type indicator("is_sorted_until_indicator_helper",
|
||||||
|
num_elements_minus_one);
|
||||||
|
::Kokkos::parallel_scan(
|
||||||
|
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements_minus_one),
|
||||||
|
functor_type(first, indicator, std::move(comp)));
|
||||||
|
|
||||||
|
// try to find the first sentinel value, which indicates
|
||||||
|
// where the sorting condition breaks
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
constexpr indicator_value_type sentinel_value = 1;
|
||||||
|
auto r =
|
||||||
|
KE::find(ex, KE::cbegin(indicator), KE::cend(indicator), sentinel_value);
|
||||||
|
const auto shift = r - ::Kokkos::Experimental::cbegin(indicator);
|
||||||
|
|
||||||
|
return first + (shift + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
IteratorType is_sorted_until_impl(const std::string& label,
|
||||||
|
const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
using value_type = typename IteratorType::value_type;
|
||||||
|
using pred_t = Impl::StdAlgoLessThanBinaryPredicate<value_type>;
|
||||||
|
return is_sorted_until_impl(label, ex, first, last, pred_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// is_sorted_impl
|
||||||
|
// ------------------------------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
bool is_sorted_impl(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
ComparatorType comp) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||||
|
Impl::expect_valid_range(first, last);
|
||||||
|
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
if (num_elements <= 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use num_elements-1 because each index handles i and i+1
|
||||||
|
const auto num_elements_minus_one = num_elements - 1;
|
||||||
|
using functor_type = StdIsSortedFunctor<IteratorType, ComparatorType>;
|
||||||
|
|
||||||
|
// result is incremented by one if sorting breaks at index i
|
||||||
|
std::size_t result = 0;
|
||||||
|
::Kokkos::parallel_reduce(
|
||||||
|
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements_minus_one),
|
||||||
|
functor_type(first, std::move(comp)), result);
|
||||||
|
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
bool is_sorted_impl(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last) {
|
||||||
|
using value_type = typename IteratorType::value_type;
|
||||||
|
using pred_t = Impl::StdAlgoLessThanBinaryPredicate<value_type>;
|
||||||
|
return is_sorted_impl(label, ex, first, last, pred_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Impl
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// is_sorted_until public API
|
||||||
|
// ----------------------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
IteratorType is_sorted_until(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
return Impl::is_sorted_until_impl(
|
||||||
|
"Kokkos::is_sorted_until_iterator_api_default", ex, first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
IteratorType is_sorted_until(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last) {
|
||||||
|
return Impl::is_sorted_until_impl(label, ex, first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto is_sorted_until(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::is_sorted_until_impl("Kokkos::is_sorted_until_view_api_default",
|
||||||
|
ex, KE::begin(view), KE::end(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto is_sorted_until(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::is_sorted_until_impl(label, ex, KE::begin(view), KE::end(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
IteratorType is_sorted_until(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
return Impl::is_sorted_until_impl(
|
||||||
|
"Kokkos::is_sorted_until_iterator_api_default", ex, first, last,
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
IteratorType is_sorted_until(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::is_sorted_until_impl(label, ex, first, last, std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ComparatorType>
|
||||||
|
auto is_sorted_until(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::is_sorted_until_impl("Kokkos::is_sorted_until_view_api_default",
|
||||||
|
ex, KE::begin(view), KE::end(view),
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ComparatorType>
|
||||||
|
auto is_sorted_until(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::is_sorted_until_impl(label, ex, KE::begin(view), KE::end(view),
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// is_sorted public API
|
||||||
|
// ----------------------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
bool is_sorted(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
return Impl::is_sorted_impl("Kokkos::is_sorted_iterator_api_default", ex,
|
||||||
|
first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
bool is_sorted(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last) {
|
||||||
|
return Impl::is_sorted_impl(label, ex, first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
bool is_sorted(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::is_sorted_impl("Kokkos::is_sorted_view_api_default", ex,
|
||||||
|
KE::cbegin(view), KE::cend(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
bool is_sorted(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::is_sorted_impl(label, ex, KE::cbegin(view), KE::cend(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
bool is_sorted(const ExecutionSpace& ex, IteratorType first, IteratorType last,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
return Impl::is_sorted_impl("Kokkos::is_sorted_iterator_api_default", ex,
|
||||||
|
first, last, std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ComparatorType>
|
||||||
|
bool is_sorted(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last, ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
return Impl::is_sorted_impl(label, ex, first, last, std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ComparatorType>
|
||||||
|
bool is_sorted(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::is_sorted_impl("Kokkos::is_sorted_view_api_default", ex,
|
||||||
|
KE::cbegin(view), KE::cend(view),
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ComparatorType>
|
||||||
|
bool is_sorted(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ComparatorType comp) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::is_sorted_impl(label, ex, KE::cbegin(view), KE::cend(view),
|
||||||
|
std::move(comp));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_VALUE_WRAPPER_FOR_NO_NEUTRAL_ELEMENT_HPP
|
||||||
|
#define KOKKOS_STD_VALUE_WRAPPER_FOR_NO_NEUTRAL_ELEMENT_HPP
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
//
|
||||||
|
// scalar wrapper used for reductions and scans
|
||||||
|
// when we don't have neutral element
|
||||||
|
//
|
||||||
|
template <class Scalar>
|
||||||
|
struct ValueWrapperForNoNeutralElement {
|
||||||
|
Scalar val;
|
||||||
|
bool is_initial = true;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator=(const ValueWrapperForNoNeutralElement& rhs) {
|
||||||
|
val = rhs.val;
|
||||||
|
is_initial = rhs.is_initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator=(const volatile ValueWrapperForNoNeutralElement& rhs) volatile {
|
||||||
|
val = rhs.val;
|
||||||
|
is_initial = rhs.is_initial;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Impl
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,279 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_NUMERICS_ADJACENT_DIFFERENCE_HPP
|
||||||
|
#define KOKKOS_STD_NUMERICS_ADJACENT_DIFFERENCE_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "../Kokkos_BeginEnd.hpp"
|
||||||
|
#include "../Kokkos_Constraints.hpp"
|
||||||
|
#include "../Kokkos_Distance.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
// ------------------------
|
||||||
|
//
|
||||||
|
// functors
|
||||||
|
//
|
||||||
|
// ------------------------
|
||||||
|
template <class ValueType1, class ValueType2, class RetType = ValueType2>
|
||||||
|
struct StdAdjacentDifferenceDefaultBinaryOpFunctor {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr RetType operator()(const ValueType1& a, const ValueType2& b) const {
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class InputIteratorType, class OutputIteratorType,
|
||||||
|
class BinaryOperator>
|
||||||
|
struct StdAdjacentDiffFunctor {
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
|
||||||
|
const InputIteratorType m_first_from;
|
||||||
|
const OutputIteratorType m_first_dest;
|
||||||
|
BinaryOperator m_op;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i) const {
|
||||||
|
const auto& my_value = m_first_from[i];
|
||||||
|
if (i == 0) {
|
||||||
|
m_first_dest[i] = my_value;
|
||||||
|
} else {
|
||||||
|
const auto& left_value = m_first_from[i - 1];
|
||||||
|
m_first_dest[i] = m_op(my_value, left_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdAdjacentDiffFunctor(InputIteratorType first_from,
|
||||||
|
OutputIteratorType first_dest, BinaryOperator op)
|
||||||
|
: m_first_from(std::move(first_from)),
|
||||||
|
m_first_dest(std::move(first_dest)),
|
||||||
|
m_op(std::move(op)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// adjacent_difference_impl
|
||||||
|
// ------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOp>
|
||||||
|
OutputIteratorType adjacent_difference_impl(const std::string& label,
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from,
|
||||||
|
InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest,
|
||||||
|
BinaryOp bin_op) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||||
|
first_dest);
|
||||||
|
Impl::expect_valid_range(first_from, last_from);
|
||||||
|
|
||||||
|
if (first_from == last_from) {
|
||||||
|
return first_dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using value_type = typename OutputIteratorType::value_type;
|
||||||
|
using aux_view_type = ::Kokkos::View<value_type*, ExecutionSpace>;
|
||||||
|
using functor_t =
|
||||||
|
StdAdjacentDiffFunctor<InputIteratorType, OutputIteratorType, BinaryOp>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(first_from, last_from);
|
||||||
|
aux_view_type aux_view("aux_view", num_elements);
|
||||||
|
::Kokkos::parallel_for(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
functor_t(first_from, first_dest, bin_op));
|
||||||
|
ex.fence("Kokkos::adjacent_difference: fence after operation");
|
||||||
|
|
||||||
|
// return
|
||||||
|
return first_dest + num_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Impl
|
||||||
|
|
||||||
|
// ------------------------
|
||||||
|
//
|
||||||
|
// public API
|
||||||
|
//
|
||||||
|
// ------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType>
|
||||||
|
std::enable_if_t<!::Kokkos::is_view<InputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
adjacent_difference(const ExecutionSpace& ex, InputIteratorType first_from,
|
||||||
|
InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest) {
|
||||||
|
using value_type1 = typename InputIteratorType::value_type;
|
||||||
|
using value_type2 = typename OutputIteratorType::value_type;
|
||||||
|
using binary_op =
|
||||||
|
Impl::StdAdjacentDifferenceDefaultBinaryOpFunctor<value_type1,
|
||||||
|
value_type2>;
|
||||||
|
return Impl::adjacent_difference_impl(
|
||||||
|
"Kokkos::adjacent_difference_iterator_api", ex, first_from, last_from,
|
||||||
|
first_dest, binary_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOp>
|
||||||
|
std::enable_if_t<!::Kokkos::is_view<InputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
adjacent_difference(const ExecutionSpace& ex, InputIteratorType first_from,
|
||||||
|
InputIteratorType last_from, OutputIteratorType first_dest,
|
||||||
|
BinaryOp bin_op) {
|
||||||
|
return Impl::adjacent_difference_impl(
|
||||||
|
"Kokkos::adjacent_difference_iterator_api", ex, first_from, last_from,
|
||||||
|
first_dest, bin_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType>
|
||||||
|
std::enable_if_t<!::Kokkos::is_view<InputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
adjacent_difference(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from, InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest) {
|
||||||
|
using value_type1 = typename InputIteratorType::value_type;
|
||||||
|
using value_type2 = typename OutputIteratorType::value_type;
|
||||||
|
using binary_op =
|
||||||
|
Impl::StdAdjacentDifferenceDefaultBinaryOpFunctor<value_type1,
|
||||||
|
value_type2>;
|
||||||
|
return Impl::adjacent_difference_impl(label, ex, first_from, last_from,
|
||||||
|
first_dest, binary_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOp>
|
||||||
|
std::enable_if_t<!::Kokkos::is_view<InputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
adjacent_difference(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from, InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest, BinaryOp bin_op) {
|
||||||
|
return Impl::adjacent_difference_impl(label, ex, first_from, last_from,
|
||||||
|
first_dest, bin_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2>
|
||||||
|
auto adjacent_difference(
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
|
||||||
|
using view_type1 = ::Kokkos::View<DataType1, Properties1...>;
|
||||||
|
using view_type2 = ::Kokkos::View<DataType2, Properties2...>;
|
||||||
|
using value_type1 = typename view_type1::value_type;
|
||||||
|
using value_type2 = typename view_type2::value_type;
|
||||||
|
using binary_op =
|
||||||
|
Impl::StdAdjacentDifferenceDefaultBinaryOpFunctor<value_type1,
|
||||||
|
value_type2>;
|
||||||
|
return Impl::adjacent_difference_impl(
|
||||||
|
"Kokkos::adjacent_difference_view_api", ex, KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest), binary_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOp>
|
||||||
|
auto adjacent_difference(
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOp bin_op) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
return Impl::adjacent_difference_impl(
|
||||||
|
"Kokkos::adjacent_difference_view_api", ex, KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest), bin_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2>
|
||||||
|
auto adjacent_difference(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
|
||||||
|
using view_type1 = ::Kokkos::View<DataType1, Properties1...>;
|
||||||
|
using view_type2 = ::Kokkos::View<DataType2, Properties2...>;
|
||||||
|
using value_type1 = typename view_type1::value_type;
|
||||||
|
using value_type2 = typename view_type2::value_type;
|
||||||
|
using binary_op =
|
||||||
|
Impl::StdAdjacentDifferenceDefaultBinaryOpFunctor<value_type1,
|
||||||
|
value_type2>;
|
||||||
|
|
||||||
|
return Impl::adjacent_difference_impl(label, ex, KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), binary_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOp>
|
||||||
|
auto adjacent_difference(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOp bin_op) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
return Impl::adjacent_difference_impl(label, ex, KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), bin_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,517 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_NUMERICS_EXCLUSIVE_SCAN_HPP
|
||||||
|
#define KOKKOS_STD_NUMERICS_EXCLUSIVE_SCAN_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "../Kokkos_BeginEnd.hpp"
|
||||||
|
#include "../Kokkos_Constraints.hpp"
|
||||||
|
#include "../Kokkos_Distance.hpp"
|
||||||
|
#include "../Kokkos_ModifyingOperations.hpp"
|
||||||
|
#include "../Kokkos_ValueWrapperForNoNeutralElement.hpp"
|
||||||
|
#include "Kokkos_IdentityReferenceUnaryFunctor.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||||
|
class FirstDest>
|
||||||
|
struct ExclusiveScanDefaultFunctor {
|
||||||
|
using execution_space = ExeSpace;
|
||||||
|
using value_type =
|
||||||
|
::Kokkos::Experimental::Impl::ValueWrapperForNoNeutralElement<ValueType>;
|
||||||
|
|
||||||
|
ValueType m_init_value;
|
||||||
|
FirstFrom m_first_from;
|
||||||
|
FirstDest m_first_dest;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
ExclusiveScanDefaultFunctor(ValueType init, FirstFrom first_from,
|
||||||
|
FirstDest first_dest)
|
||||||
|
: m_init_value(std::move(init)),
|
||||||
|
m_first_from(std::move(first_from)),
|
||||||
|
m_first_dest(std::move(first_dest)) {}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const IndexType i, value_type& update,
|
||||||
|
const bool final_pass) const {
|
||||||
|
if (final_pass) {
|
||||||
|
if (i == 0) {
|
||||||
|
m_first_dest[i] = m_init_value;
|
||||||
|
} else {
|
||||||
|
m_first_dest[i] = update.val + m_init_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto tmp = value_type{m_first_from[i], false};
|
||||||
|
this->join(update, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void init(value_type& update) const {
|
||||||
|
update.val = {};
|
||||||
|
update.is_initial = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void join(volatile value_type& update,
|
||||||
|
volatile const value_type& input) const {
|
||||||
|
if (update.is_initial) {
|
||||||
|
update.val = input.val;
|
||||||
|
update.is_initial = false;
|
||||||
|
} else {
|
||||||
|
update.val = update.val + input.val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||||
|
class FirstDest, class BinaryOpType, class UnaryOpType>
|
||||||
|
struct TransformExclusiveScanFunctor {
|
||||||
|
using execution_space = ExeSpace;
|
||||||
|
using value_type =
|
||||||
|
::Kokkos::Experimental::Impl::ValueWrapperForNoNeutralElement<ValueType>;
|
||||||
|
|
||||||
|
ValueType m_init_value;
|
||||||
|
FirstFrom m_first_from;
|
||||||
|
FirstDest m_first_dest;
|
||||||
|
BinaryOpType m_binary_op;
|
||||||
|
UnaryOpType m_unary_op;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
TransformExclusiveScanFunctor(ValueType init, FirstFrom first_from,
|
||||||
|
FirstDest first_dest, BinaryOpType bop,
|
||||||
|
UnaryOpType uop)
|
||||||
|
: m_init_value(std::move(init)),
|
||||||
|
m_first_from(std::move(first_from)),
|
||||||
|
m_first_dest(std::move(first_dest)),
|
||||||
|
m_binary_op(std::move(bop)),
|
||||||
|
m_unary_op(std::move(uop)) {}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const IndexType i, value_type& update,
|
||||||
|
const bool final_pass) const {
|
||||||
|
if (final_pass) {
|
||||||
|
if (i == 0) {
|
||||||
|
// for both ExclusiveScan and TransformExclusiveScan,
|
||||||
|
// init is unmodified
|
||||||
|
m_first_dest[i] = m_init_value;
|
||||||
|
} else {
|
||||||
|
m_first_dest[i] = m_binary_op(update.val, m_init_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto tmp = value_type{m_unary_op(m_first_from[i]), false};
|
||||||
|
this->join(update, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void init(value_type& update) const {
|
||||||
|
update.val = {};
|
||||||
|
update.is_initial = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void join(volatile value_type& update,
|
||||||
|
volatile const value_type& input) const {
|
||||||
|
if (update.is_initial) {
|
||||||
|
update.val = input.val;
|
||||||
|
} else {
|
||||||
|
update.val = m_binary_op(update.val, input.val);
|
||||||
|
}
|
||||||
|
update.is_initial = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// exclusive_scan_custom_op_impl
|
||||||
|
// --------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class ValueType, class BinaryOpType>
|
||||||
|
OutputIteratorType exclusive_scan_custom_op_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from, InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest, ValueType init_value, BinaryOpType bop) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||||
|
first_dest);
|
||||||
|
Impl::expect_valid_range(first_from, last_from);
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
using unary_op_type = StdNumericScanIdentityReferenceUnaryFunctor<ValueType>;
|
||||||
|
using func_type =
|
||||||
|
TransformExclusiveScanFunctor<ExecutionSpace, index_type, ValueType,
|
||||||
|
InputIteratorType, OutputIteratorType,
|
||||||
|
BinaryOpType, unary_op_type>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(first_from, last_from);
|
||||||
|
::Kokkos::parallel_scan(
|
||||||
|
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_type(init_value, first_from, first_dest, bop, unary_op_type()));
|
||||||
|
ex.fence("Kokkos::exclusive_scan_custom_op: fence after operation");
|
||||||
|
|
||||||
|
// return
|
||||||
|
return first_dest + num_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// transform_exclusive_scan_impl
|
||||||
|
// --------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class ValueType, class BinaryOpType,
|
||||||
|
class UnaryOpType>
|
||||||
|
OutputIteratorType transform_exclusive_scan_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from, InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest, ValueType init_value, BinaryOpType bop,
|
||||||
|
UnaryOpType uop) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||||
|
first_dest);
|
||||||
|
Impl::expect_valid_range(first_from, last_from);
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
using func_type =
|
||||||
|
TransformExclusiveScanFunctor<ExecutionSpace, index_type, ValueType,
|
||||||
|
InputIteratorType, OutputIteratorType,
|
||||||
|
BinaryOpType, UnaryOpType>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(first_from, last_from);
|
||||||
|
::Kokkos::parallel_scan(
|
||||||
|
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_type(init_value, first_from, first_dest, bop, uop));
|
||||||
|
ex.fence("Kokkos::transform_exclusive_scan: fence after operation");
|
||||||
|
|
||||||
|
// return
|
||||||
|
return first_dest + num_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// exclusive_scan_default_op_impl
|
||||||
|
// --------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class ValueType>
|
||||||
|
OutputIteratorType exclusive_scan_default_op_impl(const std::string& label,
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from,
|
||||||
|
InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest,
|
||||||
|
ValueType init_value) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||||
|
first_dest);
|
||||||
|
Impl::expect_valid_range(first_from, last_from);
|
||||||
|
|
||||||
|
// does it make sense to do this static_assert too?
|
||||||
|
// using input_iterator_value_type = typename InputIteratorType::value_type;
|
||||||
|
// static_assert
|
||||||
|
// (std::is_convertible<std::remove_cv_t<input_iterator_value_type>,
|
||||||
|
// ValueType>::value,
|
||||||
|
// "exclusive_scan: InputIteratorType::value_type not convertible to
|
||||||
|
// ValueType");
|
||||||
|
|
||||||
|
// we are unnecessarily duplicating code, but this is on purpose
|
||||||
|
// so that we can use the default_op for OpenMPTarget.
|
||||||
|
// Originally, I had this implemented as:
|
||||||
|
// '''
|
||||||
|
// using bop_type = StdExclusiveScanDefaultJoinFunctor<ValueType>;
|
||||||
|
// call exclusive_scan_custom_op_impl(..., bop_type());
|
||||||
|
// '''
|
||||||
|
// which avoids duplicating the functors, but for OpenMPTarget
|
||||||
|
// I cannot use a custom binary op.
|
||||||
|
// This is the same problem that occurs for reductions.
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
using func_type =
|
||||||
|
ExclusiveScanDefaultFunctor<ExecutionSpace, index_type, ValueType,
|
||||||
|
InputIteratorType, OutputIteratorType>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(first_from, last_from);
|
||||||
|
::Kokkos::parallel_scan(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_type(init_value, first_from, first_dest));
|
||||||
|
ex.fence("Kokkos::exclusive_scan_default_op: fence after operation");
|
||||||
|
|
||||||
|
return first_dest + num_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Impl
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
//
|
||||||
|
// exclusive scan API
|
||||||
|
//
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
// overload set 1
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class ValueType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
exclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||||
|
InputIteratorType last, OutputIteratorType first_dest,
|
||||||
|
ValueType init_value) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
return Impl::exclusive_scan_default_op_impl(
|
||||||
|
"Kokkos::exclusive_scan_default_functors_iterator_api", ex, first, last,
|
||||||
|
first_dest, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class ValueType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first, InputIteratorType last,
|
||||||
|
OutputIteratorType first_dest, ValueType init_value) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
return Impl::exclusive_scan_default_op_impl(label, ex, first, last,
|
||||||
|
first_dest, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType>
|
||||||
|
auto exclusive_scan(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
ValueType init_value) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::exclusive_scan_default_op_impl(
|
||||||
|
"Kokkos::exclusive_scan_default_functors_view_api", ex,
|
||||||
|
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType>
|
||||||
|
auto exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
ValueType init_value) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::exclusive_scan_default_op_impl(label, ex, KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// overload set 2
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class ValueType, class BinaryOpType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
exclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||||
|
InputIteratorType last, OutputIteratorType first_dest,
|
||||||
|
ValueType init_value, BinaryOpType bop) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
return Impl::exclusive_scan_custom_op_impl(
|
||||||
|
"Kokkos::exclusive_scan_custom_functors_iterator_api", ex, first, last,
|
||||||
|
first_dest, init_value, bop);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class ValueType, class BinaryOpType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first, InputIteratorType last,
|
||||||
|
OutputIteratorType first_dest, ValueType init_value,
|
||||||
|
BinaryOpType bop) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
return Impl::exclusive_scan_custom_op_impl(label, ex, first, last, first_dest,
|
||||||
|
init_value, bop);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType,
|
||||||
|
class BinaryOpType>
|
||||||
|
auto exclusive_scan(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
ValueType init_value, BinaryOpType bop) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::exclusive_scan_custom_op_impl(
|
||||||
|
"Kokkos::exclusive_scan_custom_functors_view_api", ex,
|
||||||
|
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
init_value, bop);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType,
|
||||||
|
class BinaryOpType>
|
||||||
|
auto exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
ValueType init_value, BinaryOpType bop) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::exclusive_scan_custom_op_impl(
|
||||||
|
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), init_value, bop);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
//
|
||||||
|
// transform_exclusive_scan public API
|
||||||
|
//
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class ValueType, class BinaryOpType,
|
||||||
|
class UnaryOpType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
transform_exclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||||
|
InputIteratorType last, OutputIteratorType first_dest,
|
||||||
|
ValueType init_value, BinaryOpType binary_op,
|
||||||
|
UnaryOpType unary_op) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
return Impl::transform_exclusive_scan_impl(
|
||||||
|
"Kokkos::transform_exclusive_scan_custom_functors_iterator_api", ex,
|
||||||
|
first, last, first_dest, init_value, binary_op, unary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class ValueType, class BinaryOpType,
|
||||||
|
class UnaryOpType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
transform_exclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first, InputIteratorType last,
|
||||||
|
OutputIteratorType first_dest, ValueType init_value,
|
||||||
|
BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
return Impl::transform_exclusive_scan_impl(label, ex, first, last, first_dest,
|
||||||
|
init_value, binary_op, unary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType,
|
||||||
|
class BinaryOpType, class UnaryOpType>
|
||||||
|
auto transform_exclusive_scan(
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
ValueType init_value, BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::transform_exclusive_scan_impl(
|
||||||
|
"Kokkos::transform_exclusive_scan_custom_functors_view_api", ex,
|
||||||
|
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
init_value, binary_op, unary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType,
|
||||||
|
class BinaryOpType, class UnaryOpType>
|
||||||
|
auto transform_exclusive_scan(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
ValueType init_value, BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::transform_exclusive_scan_impl(
|
||||||
|
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), init_value, binary_op, unary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_NUMERIC_IDENTITY_REFERENCE_UNARY_FUNCTOR_HPP
|
||||||
|
#define KOKKOS_STD_NUMERIC_IDENTITY_REFERENCE_UNARY_FUNCTOR_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Macros.hpp>
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct StdNumericScanIdentityReferenceUnaryFunctor {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr const ValueType& operator()(const ValueType& a) const { return a; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Impl
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,699 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_NUMERICS_INCLUSIVE_SCAN_HPP
|
||||||
|
#define KOKKOS_STD_NUMERICS_INCLUSIVE_SCAN_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "../Kokkos_BeginEnd.hpp"
|
||||||
|
#include "../Kokkos_Constraints.hpp"
|
||||||
|
#include "../Kokkos_Distance.hpp"
|
||||||
|
#include "../Kokkos_ModifyingOperations.hpp"
|
||||||
|
#include "../Kokkos_ValueWrapperForNoNeutralElement.hpp"
|
||||||
|
#include "Kokkos_IdentityReferenceUnaryFunctor.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||||
|
class FirstDest>
|
||||||
|
struct InclusiveScanDefaultFunctor {
|
||||||
|
using execution_space = ExeSpace;
|
||||||
|
using value_type = ValueWrapperForNoNeutralElement<ValueType>;
|
||||||
|
|
||||||
|
FirstFrom m_first_from;
|
||||||
|
FirstDest m_first_dest;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
InclusiveScanDefaultFunctor(FirstFrom first_from, FirstDest first_dest)
|
||||||
|
: m_first_from(std::move(first_from)),
|
||||||
|
m_first_dest(std::move(first_dest)) {}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const IndexType i, value_type& update,
|
||||||
|
const bool final_pass) const {
|
||||||
|
const auto tmp = value_type{m_first_from[i], false};
|
||||||
|
this->join(update, tmp);
|
||||||
|
|
||||||
|
if (final_pass) {
|
||||||
|
m_first_dest[i] = update.val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void init(value_type& update) const {
|
||||||
|
update.val = {};
|
||||||
|
update.is_initial = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void join(volatile value_type& update,
|
||||||
|
volatile const value_type& input) const {
|
||||||
|
if (update.is_initial) {
|
||||||
|
update.val = input.val;
|
||||||
|
} else {
|
||||||
|
update.val = update.val + input.val;
|
||||||
|
}
|
||||||
|
update.is_initial = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||||
|
class FirstDest, class BinaryOpType, class UnaryOpType>
|
||||||
|
struct TransformInclusiveScanNoInitValueFunctor {
|
||||||
|
using execution_space = ExeSpace;
|
||||||
|
using value_type = ValueWrapperForNoNeutralElement<ValueType>;
|
||||||
|
|
||||||
|
FirstFrom m_first_from;
|
||||||
|
FirstDest m_first_dest;
|
||||||
|
BinaryOpType m_binary_op;
|
||||||
|
UnaryOpType m_unary_op;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
TransformInclusiveScanNoInitValueFunctor(FirstFrom first_from,
|
||||||
|
FirstDest first_dest,
|
||||||
|
BinaryOpType bop, UnaryOpType uop)
|
||||||
|
: m_first_from(std::move(first_from)),
|
||||||
|
m_first_dest(std::move(first_dest)),
|
||||||
|
m_binary_op(std::move(bop)),
|
||||||
|
m_unary_op(std::move(uop)) {}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const IndexType i, value_type& update,
|
||||||
|
const bool final_pass) const {
|
||||||
|
const auto tmp = value_type{m_unary_op(m_first_from[i]), false};
|
||||||
|
this->join(update, tmp);
|
||||||
|
if (final_pass) {
|
||||||
|
m_first_dest[i] = update.val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void init(value_type& update) const {
|
||||||
|
update.val = {};
|
||||||
|
update.is_initial = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void join(volatile value_type& update,
|
||||||
|
volatile const value_type& input) const {
|
||||||
|
if (update.is_initial) {
|
||||||
|
update.val = input.val;
|
||||||
|
} else {
|
||||||
|
update.val = m_binary_op(update.val, input.val);
|
||||||
|
}
|
||||||
|
update.is_initial = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ExeSpace, class IndexType, class ValueType, class FirstFrom,
|
||||||
|
class FirstDest, class BinaryOpType, class UnaryOpType>
|
||||||
|
struct TransformInclusiveScanWithInitValueFunctor {
|
||||||
|
using execution_space = ExeSpace;
|
||||||
|
using value_type = ValueWrapperForNoNeutralElement<ValueType>;
|
||||||
|
|
||||||
|
FirstFrom m_first_from;
|
||||||
|
FirstDest m_first_dest;
|
||||||
|
BinaryOpType m_binary_op;
|
||||||
|
UnaryOpType m_unary_op;
|
||||||
|
ValueType m_init;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
TransformInclusiveScanWithInitValueFunctor(FirstFrom first_from,
|
||||||
|
FirstDest first_dest,
|
||||||
|
BinaryOpType bop, UnaryOpType uop,
|
||||||
|
ValueType init)
|
||||||
|
: m_first_from(std::move(first_from)),
|
||||||
|
m_first_dest(std::move(first_dest)),
|
||||||
|
m_binary_op(std::move(bop)),
|
||||||
|
m_unary_op(std::move(uop)),
|
||||||
|
m_init(std::move(init)) {}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const IndexType i, value_type& update,
|
||||||
|
const bool final_pass) const {
|
||||||
|
const auto tmp = value_type{m_unary_op(m_first_from[i]), false};
|
||||||
|
this->join(update, tmp);
|
||||||
|
|
||||||
|
if (final_pass) {
|
||||||
|
m_first_dest[i] = m_binary_op(update.val, m_init);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void init(value_type& update) const {
|
||||||
|
update.val = {};
|
||||||
|
update.is_initial = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void join(volatile value_type& update,
|
||||||
|
volatile const value_type& input) const {
|
||||||
|
if (update.is_initial) {
|
||||||
|
update.val = input.val;
|
||||||
|
} else {
|
||||||
|
update.val = m_binary_op(update.val, input.val);
|
||||||
|
}
|
||||||
|
update.is_initial = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// inclusive_scan_default_op_impl
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType>
|
||||||
|
OutputIteratorType inclusive_scan_default_op_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from, InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||||
|
first_dest);
|
||||||
|
Impl::expect_valid_range(first_from, last_from);
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
using value_type =
|
||||||
|
std::remove_const_t<typename InputIteratorType::value_type>;
|
||||||
|
using func_type =
|
||||||
|
InclusiveScanDefaultFunctor<ExecutionSpace, index_type, value_type,
|
||||||
|
InputIteratorType, OutputIteratorType>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(first_from, last_from);
|
||||||
|
::Kokkos::parallel_scan(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_type(first_from, first_dest));
|
||||||
|
ex.fence("Kokkos::inclusive_scan_default_op: fence after operation");
|
||||||
|
|
||||||
|
// return
|
||||||
|
return first_dest + num_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// inclusive_scan_custom_binary_op_impl
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOpType>
|
||||||
|
OutputIteratorType inclusive_scan_custom_binary_op_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from, InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest, BinaryOpType binary_op) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||||
|
first_dest);
|
||||||
|
Impl::expect_valid_range(first_from, last_from);
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
using value_type =
|
||||||
|
std::remove_const_t<typename InputIteratorType::value_type>;
|
||||||
|
using unary_op_type = StdNumericScanIdentityReferenceUnaryFunctor<value_type>;
|
||||||
|
using func_type = TransformInclusiveScanNoInitValueFunctor<
|
||||||
|
ExecutionSpace, index_type, value_type, InputIteratorType,
|
||||||
|
OutputIteratorType, BinaryOpType, unary_op_type>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(first_from, last_from);
|
||||||
|
::Kokkos::parallel_scan(
|
||||||
|
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_type(first_from, first_dest, binary_op, unary_op_type()));
|
||||||
|
ex.fence("Kokkos::inclusive_scan_custom_binary_op: fence after operation");
|
||||||
|
|
||||||
|
// return
|
||||||
|
return first_dest + num_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// inclusive_scan_custom_binary_op_impl with init_value
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOpType, class ValueType>
|
||||||
|
OutputIteratorType inclusive_scan_custom_binary_op_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from, InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest, BinaryOpType binary_op,
|
||||||
|
ValueType init_value) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||||
|
first_dest);
|
||||||
|
Impl::expect_valid_range(first_from, last_from);
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
using unary_op_type = StdNumericScanIdentityReferenceUnaryFunctor<ValueType>;
|
||||||
|
using func_type = TransformInclusiveScanWithInitValueFunctor<
|
||||||
|
ExecutionSpace, index_type, ValueType, InputIteratorType,
|
||||||
|
OutputIteratorType, BinaryOpType, unary_op_type>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(first_from, last_from);
|
||||||
|
::Kokkos::parallel_scan(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_type(first_from, first_dest, binary_op,
|
||||||
|
unary_op_type(), init_value));
|
||||||
|
ex.fence("Kokkos::inclusive_scan_custom_binary_op: fence after operation");
|
||||||
|
|
||||||
|
// return
|
||||||
|
return first_dest + num_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// transform_inclusive_scan_impl without init_value
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOpType, class UnaryOpType>
|
||||||
|
OutputIteratorType transform_inclusive_scan_impl(const std::string& label,
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from,
|
||||||
|
InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest,
|
||||||
|
BinaryOpType binary_op,
|
||||||
|
UnaryOpType unary_op) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||||
|
first_dest);
|
||||||
|
Impl::expect_valid_range(first_from, last_from);
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
using value_type =
|
||||||
|
std::remove_const_t<typename InputIteratorType::value_type>;
|
||||||
|
using func_type = TransformInclusiveScanNoInitValueFunctor<
|
||||||
|
ExecutionSpace, index_type, value_type, InputIteratorType,
|
||||||
|
OutputIteratorType, BinaryOpType, UnaryOpType>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(first_from, last_from);
|
||||||
|
::Kokkos::parallel_scan(
|
||||||
|
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_type(first_from, first_dest, binary_op, unary_op));
|
||||||
|
ex.fence("Kokkos::transform_inclusive_scan: fence after operation");
|
||||||
|
|
||||||
|
// return
|
||||||
|
return first_dest + num_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// transform_inclusive_scan_impl with init_value
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOpType, class UnaryOpType,
|
||||||
|
class ValueType>
|
||||||
|
OutputIteratorType transform_inclusive_scan_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first_from, InputIteratorType last_from,
|
||||||
|
OutputIteratorType first_dest, BinaryOpType binary_op, UnaryOpType unary_op,
|
||||||
|
ValueType init_value) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first_from, first_dest);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first_from,
|
||||||
|
first_dest);
|
||||||
|
Impl::expect_valid_range(first_from, last_from);
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename InputIteratorType::difference_type;
|
||||||
|
using func_type = TransformInclusiveScanWithInitValueFunctor<
|
||||||
|
ExecutionSpace, index_type, ValueType, InputIteratorType,
|
||||||
|
OutputIteratorType, BinaryOpType, UnaryOpType>;
|
||||||
|
|
||||||
|
// run
|
||||||
|
const auto num_elements =
|
||||||
|
Kokkos::Experimental::distance(first_from, last_from);
|
||||||
|
::Kokkos::parallel_scan(
|
||||||
|
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_type(first_from, first_dest, binary_op, unary_op, init_value));
|
||||||
|
ex.fence("Kokkos::transform_inclusive_scan: fence after operation");
|
||||||
|
|
||||||
|
// return
|
||||||
|
return first_dest + num_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Impl
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
//
|
||||||
|
// inclusive scan API
|
||||||
|
//
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
// overload set 1
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||||
|
InputIteratorType last, OutputIteratorType first_dest) {
|
||||||
|
return Impl::inclusive_scan_default_op_impl(
|
||||||
|
"Kokkos::inclusive_scan_default_functors_iterator_api", ex, first, last,
|
||||||
|
first_dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first, InputIteratorType last,
|
||||||
|
OutputIteratorType first_dest) {
|
||||||
|
return Impl::inclusive_scan_default_op_impl(label, ex, first, last,
|
||||||
|
first_dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2>
|
||||||
|
auto inclusive_scan(
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::inclusive_scan_default_op_impl(
|
||||||
|
"Kokkos::inclusive_scan_default_functors_view_api", ex,
|
||||||
|
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2>
|
||||||
|
auto inclusive_scan(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::inclusive_scan_default_op_impl(label, ex, KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from),
|
||||||
|
KE::begin(view_dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
// overload set 2 (accepting custom binary op)
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOp>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||||
|
InputIteratorType last, OutputIteratorType first_dest,
|
||||||
|
BinaryOp binary_op) {
|
||||||
|
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||||
|
"Kokkos::inclusive_scan_custom_functors_iterator_api", ex, first, last,
|
||||||
|
first_dest, binary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOp>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first, InputIteratorType last,
|
||||||
|
OutputIteratorType first_dest, BinaryOp binary_op) {
|
||||||
|
return Impl::inclusive_scan_custom_binary_op_impl(label, ex, first, last,
|
||||||
|
first_dest, binary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOp>
|
||||||
|
auto inclusive_scan(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOp binary_op) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||||
|
"Kokkos::inclusive_scan_custom_functors_view_api", ex,
|
||||||
|
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
binary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOp>
|
||||||
|
auto inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOp binary_op) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||||
|
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), binary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
// overload set 3
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOp, class ValueType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||||
|
InputIteratorType last, OutputIteratorType first_dest,
|
||||||
|
BinaryOp binary_op, ValueType init_value) {
|
||||||
|
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||||
|
"Kokkos::inclusive_scan_custom_functors_iterator_api", ex, first, last,
|
||||||
|
first_dest, binary_op, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOp, class ValueType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first, InputIteratorType last,
|
||||||
|
OutputIteratorType first_dest, BinaryOp binary_op,
|
||||||
|
ValueType init_value) {
|
||||||
|
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||||
|
label, ex, first, last, first_dest, binary_op, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOp,
|
||||||
|
class ValueType>
|
||||||
|
auto inclusive_scan(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOp binary_op, ValueType init_value) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||||
|
"Kokkos::inclusive_scan_custom_functors_view_api", ex,
|
||||||
|
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
binary_op, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOp,
|
||||||
|
class ValueType>
|
||||||
|
auto inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOp binary_op, ValueType init_value) {
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::inclusive_scan_custom_binary_op_impl(
|
||||||
|
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), binary_op, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
//
|
||||||
|
// transform_inclusive_scan public API
|
||||||
|
//
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
// overload set 1 (no init value)
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOpType, class UnaryOpType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
transform_inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||||
|
InputIteratorType last, OutputIteratorType first_dest,
|
||||||
|
BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::transform_inclusive_scan_impl(
|
||||||
|
"Kokkos::transform_inclusive_scan_custom_functors_iterator_api", ex,
|
||||||
|
first, last, first_dest, binary_op, unary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOpType, class UnaryOpType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
transform_inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first, InputIteratorType last,
|
||||||
|
OutputIteratorType first_dest, BinaryOpType binary_op,
|
||||||
|
UnaryOpType unary_op) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
|
||||||
|
return Impl::transform_inclusive_scan_impl(label, ex, first, last, first_dest,
|
||||||
|
binary_op, unary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOpType,
|
||||||
|
class UnaryOpType>
|
||||||
|
auto transform_inclusive_scan(
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::transform_inclusive_scan_impl(
|
||||||
|
"Kokkos::transform_inclusive_scan_custom_functors_view_api", ex,
|
||||||
|
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
binary_op, unary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOpType,
|
||||||
|
class UnaryOpType>
|
||||||
|
auto transform_inclusive_scan(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOpType binary_op, UnaryOpType unary_op) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::transform_inclusive_scan_impl(
|
||||||
|
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), binary_op, unary_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
// overload set 2 (init value)
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOpType, class UnaryOpType,
|
||||||
|
class ValueType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
transform_inclusive_scan(const ExecutionSpace& ex, InputIteratorType first,
|
||||||
|
InputIteratorType last, OutputIteratorType first_dest,
|
||||||
|
BinaryOpType binary_op, UnaryOpType unary_op,
|
||||||
|
ValueType init_value) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
return Impl::transform_inclusive_scan_impl(
|
||||||
|
"Kokkos::transform_inclusive_scan_custom_functors_iterator_api", ex,
|
||||||
|
first, last, first_dest, binary_op, unary_op, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class InputIteratorType,
|
||||||
|
class OutputIteratorType, class BinaryOpType, class UnaryOpType,
|
||||||
|
class ValueType>
|
||||||
|
std::enable_if_t< ::Kokkos::Experimental::Impl::are_iterators<
|
||||||
|
InputIteratorType, OutputIteratorType>::value,
|
||||||
|
OutputIteratorType>
|
||||||
|
transform_inclusive_scan(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
InputIteratorType first, InputIteratorType last,
|
||||||
|
OutputIteratorType first_dest, BinaryOpType binary_op,
|
||||||
|
UnaryOpType unary_op, ValueType init_value) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
return Impl::transform_inclusive_scan_impl(label, ex, first, last, first_dest,
|
||||||
|
binary_op, unary_op, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOpType,
|
||||||
|
class UnaryOpType, class ValueType>
|
||||||
|
auto transform_inclusive_scan(
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOpType binary_op, UnaryOpType unary_op, ValueType init_value) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::transform_inclusive_scan_impl(
|
||||||
|
"Kokkos::transform_inclusive_scan_custom_functors_view_api", ex,
|
||||||
|
KE::cbegin(view_from), KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
binary_op, unary_op, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class BinaryOpType,
|
||||||
|
class UnaryOpType, class ValueType>
|
||||||
|
auto transform_inclusive_scan(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& view_from,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& view_dest,
|
||||||
|
BinaryOpType binary_op, UnaryOpType unary_op, ValueType init_value) {
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_from);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view_dest);
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
return Impl::transform_inclusive_scan_impl(
|
||||||
|
label, ex, KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), binary_op, unary_op, init_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,326 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_NUMERICS_REDUCE_HPP
|
||||||
|
#define KOKKOS_STD_NUMERICS_REDUCE_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "../Kokkos_BeginEnd.hpp"
|
||||||
|
#include "../Kokkos_Constraints.hpp"
|
||||||
|
#include "../Kokkos_Distance.hpp"
|
||||||
|
#include "../Kokkos_ModifyingOperations.hpp"
|
||||||
|
#include "../Kokkos_ReducerWithArbitraryJoinerNoNeutralElement.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct StdReduceDefaultJoinFunctor {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr ValueType operator()(const volatile ValueType& a,
|
||||||
|
const volatile ValueType& b) const {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IteratorType, class ReducerType>
|
||||||
|
struct StdReduceFunctor {
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
|
||||||
|
const IteratorType m_first;
|
||||||
|
const ReducerType m_reducer;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i, red_value_type& red_value) const {
|
||||||
|
auto tmp_wrapped_value = red_value_type{m_first[i], false};
|
||||||
|
|
||||||
|
if (red_value.is_initial) {
|
||||||
|
red_value = tmp_wrapped_value;
|
||||||
|
} else {
|
||||||
|
m_reducer.join(red_value, tmp_wrapped_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdReduceFunctor(IteratorType first, ReducerType reducer)
|
||||||
|
: m_first(std::move(first)), m_reducer(std::move(reducer)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------
|
||||||
|
// reduce_custom_functors_impl
|
||||||
|
//------------------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||||
|
class JoinerType>
|
||||||
|
ValueType reduce_custom_functors_impl(const std::string& label,
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
ValueType init_reduction_value,
|
||||||
|
JoinerType joiner) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::expect_valid_range(first, last);
|
||||||
|
|
||||||
|
if (first == last) {
|
||||||
|
// init is returned, unmodified
|
||||||
|
return init_reduction_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using reducer_type =
|
||||||
|
ReducerWithArbitraryJoinerNoNeutralElement<ValueType, JoinerType>;
|
||||||
|
using functor_type = StdReduceFunctor<IteratorType, reducer_type>;
|
||||||
|
using reduction_value_type = typename reducer_type::value_type;
|
||||||
|
|
||||||
|
// run
|
||||||
|
reduction_value_type result;
|
||||||
|
reducer_type reducer(result, joiner);
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
::Kokkos::parallel_reduce(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
functor_type(first, reducer), reducer);
|
||||||
|
|
||||||
|
// fence not needed since reducing into scalar
|
||||||
|
return joiner(result.val, init_reduction_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ValueType>
|
||||||
|
ValueType reduce_default_functors_impl(const std::string& label,
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
ValueType init_reduction_value) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::expect_valid_range(first, last);
|
||||||
|
|
||||||
|
using value_type = Kokkos::Impl::remove_cvref_t<ValueType>;
|
||||||
|
using joiner_type = Impl::StdReduceDefaultJoinFunctor<value_type>;
|
||||||
|
return reduce_custom_functors_impl(
|
||||||
|
label, ex, first, last, std::move(init_reduction_value), joiner_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Impl
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
//
|
||||||
|
// reduce public API
|
||||||
|
//
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
//
|
||||||
|
// overload set 1
|
||||||
|
//
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
typename IteratorType::value_type reduce(const ExecutionSpace& ex,
|
||||||
|
IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
return Impl::reduce_default_functors_impl(
|
||||||
|
"Kokkos::reduce_default_functors_iterator_api", ex, first, last,
|
||||||
|
typename IteratorType::value_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
typename IteratorType::value_type reduce(const std::string& label,
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
return Impl::reduce_default_functors_impl(
|
||||||
|
label, ex, first, last, typename IteratorType::value_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto reduce(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
using view_type = ::Kokkos::View<DataType, Properties...>;
|
||||||
|
using value_type = typename view_type::value_type;
|
||||||
|
|
||||||
|
return Impl::reduce_default_functors_impl(
|
||||||
|
"Kokkos::reduce_default_functors_view_api", ex, KE::cbegin(view),
|
||||||
|
KE::cend(view), value_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties>
|
||||||
|
auto reduce(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
using view_type = ::Kokkos::View<DataType, Properties...>;
|
||||||
|
using value_type = typename view_type::value_type;
|
||||||
|
|
||||||
|
return Impl::reduce_default_functors_impl(label, ex, KE::cbegin(view),
|
||||||
|
KE::cend(view), value_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// overload set2:
|
||||||
|
//
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ValueType>
|
||||||
|
ValueType reduce(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, ValueType init_reduction_value) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
return Impl::reduce_default_functors_impl(
|
||||||
|
"Kokkos::reduce_default_functors_iterator_api", ex, first, last,
|
||||||
|
init_reduction_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ValueType>
|
||||||
|
ValueType reduce(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
ValueType init_reduction_value) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
return Impl::reduce_default_functors_impl(label, ex, first, last,
|
||||||
|
init_reduction_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ValueType>
|
||||||
|
ValueType reduce(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ValueType init_reduction_value) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
return Impl::reduce_default_functors_impl(
|
||||||
|
"Kokkos::reduce_default_functors_view_api", ex, KE::cbegin(view),
|
||||||
|
KE::cend(view), init_reduction_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ValueType>
|
||||||
|
ValueType reduce(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ValueType init_reduction_value) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
return Impl::reduce_default_functors_impl(
|
||||||
|
label, ex, KE::cbegin(view), KE::cend(view), init_reduction_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// overload set 3
|
||||||
|
//
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||||
|
class BinaryOp>
|
||||||
|
ValueType reduce(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, ValueType init_reduction_value,
|
||||||
|
BinaryOp joiner) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
return Impl::reduce_custom_functors_impl(
|
||||||
|
"Kokkos::reduce_default_functors_iterator_api", ex, first, last,
|
||||||
|
init_reduction_value, joiner);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||||
|
class BinaryOp>
|
||||||
|
ValueType reduce(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first, IteratorType last,
|
||||||
|
ValueType init_reduction_value, BinaryOp joiner) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
return Impl::reduce_custom_functors_impl(label, ex, first, last,
|
||||||
|
init_reduction_value, joiner);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ValueType, class BinaryOp>
|
||||||
|
ValueType reduce(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ValueType init_reduction_value, BinaryOp joiner) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
return Impl::reduce_custom_functors_impl(
|
||||||
|
"Kokkos::reduce_custom_functors_view_api", ex, KE::cbegin(view),
|
||||||
|
KE::cend(view), init_reduction_value, joiner);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ValueType, class BinaryOp>
|
||||||
|
ValueType reduce(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ValueType init_reduction_value, BinaryOp joiner) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
return Impl::reduce_custom_functors_impl(label, ex, KE::cbegin(view),
|
||||||
|
KE::cend(view), init_reduction_value,
|
||||||
|
joiner);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,488 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_STD_NUMERICS_TRANSFORM_REDUCE_HPP
|
||||||
|
#define KOKKOS_STD_NUMERICS_TRANSFORM_REDUCE_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include "../Kokkos_Constraints.hpp"
|
||||||
|
#include "../Kokkos_Distance.hpp"
|
||||||
|
#include "../Kokkos_ModifyingOperations.hpp"
|
||||||
|
#include "../Kokkos_BeginEnd.hpp"
|
||||||
|
#include "../Kokkos_ReducerWithArbitraryJoinerNoNeutralElement.hpp"
|
||||||
|
|
||||||
|
namespace Kokkos {
|
||||||
|
namespace Experimental {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
//
|
||||||
|
// helper functors
|
||||||
|
//
|
||||||
|
template <class ValueType>
|
||||||
|
struct StdTranformReduceDefaultBinaryTransformFunctor {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return (a * b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct StdTranformReduceDefaultJoinFunctor {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
constexpr ValueType operator()(const volatile ValueType& a,
|
||||||
|
const volatile ValueType& b) const {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IteratorType, class ReducerType, class TransformType>
|
||||||
|
struct StdTransformReduceSingleIntervalFunctor {
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
|
||||||
|
const IteratorType m_first;
|
||||||
|
const ReducerType m_reducer;
|
||||||
|
const TransformType m_transform;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i, red_value_type& red_value) const {
|
||||||
|
auto tmp_wrapped_value = red_value_type{m_transform(m_first[i]), false};
|
||||||
|
if (red_value.is_initial) {
|
||||||
|
red_value = tmp_wrapped_value;
|
||||||
|
} else {
|
||||||
|
m_reducer.join(red_value, tmp_wrapped_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdTransformReduceSingleIntervalFunctor(IteratorType first,
|
||||||
|
ReducerType reducer,
|
||||||
|
TransformType transform)
|
||||||
|
: m_first(std::move(first)),
|
||||||
|
m_reducer(std::move(reducer)),
|
||||||
|
m_transform(std::move(transform)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IndexType, class IteratorType1, class IteratorType2,
|
||||||
|
class ReducerType, class TransformType>
|
||||||
|
struct StdTransformReduceTwoIntervalsFunctor {
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
|
||||||
|
const IteratorType1 m_first1;
|
||||||
|
const IteratorType2 m_first2;
|
||||||
|
const ReducerType m_reducer;
|
||||||
|
const TransformType m_transform;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const IndexType i, red_value_type& red_value) const {
|
||||||
|
auto tmp_wrapped_value =
|
||||||
|
red_value_type{m_transform(m_first1[i], m_first2[i]), false};
|
||||||
|
|
||||||
|
if (red_value.is_initial) {
|
||||||
|
red_value = tmp_wrapped_value;
|
||||||
|
} else {
|
||||||
|
m_reducer.join(red_value, tmp_wrapped_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdTransformReduceTwoIntervalsFunctor(IteratorType1 first1,
|
||||||
|
IteratorType2 first2,
|
||||||
|
ReducerType reducer,
|
||||||
|
TransformType transform)
|
||||||
|
: m_first1(std::move(first1)),
|
||||||
|
m_first2(std::move(first2)),
|
||||||
|
m_reducer(std::move(reducer)),
|
||||||
|
m_transform(std::move(transform)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------
|
||||||
|
//
|
||||||
|
// impl functions
|
||||||
|
//
|
||||||
|
//------------------------------
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||||
|
class JoinerType, class UnaryTransformerType>
|
||||||
|
ValueType transform_reduce_custom_functors_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last, ValueType init_reduction_value, JoinerType joiner,
|
||||||
|
UnaryTransformerType transformer) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::expect_valid_range(first, last);
|
||||||
|
|
||||||
|
if (first == last) {
|
||||||
|
// init is returned, unmodified
|
||||||
|
return init_reduction_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using reducer_type =
|
||||||
|
ReducerWithArbitraryJoinerNoNeutralElement<ValueType, JoinerType>;
|
||||||
|
using functor_type =
|
||||||
|
StdTransformReduceSingleIntervalFunctor<IteratorType, reducer_type,
|
||||||
|
UnaryTransformerType>;
|
||||||
|
using reduction_value_type = typename reducer_type::value_type;
|
||||||
|
|
||||||
|
// run
|
||||||
|
reduction_value_type result;
|
||||||
|
reducer_type reducer(result, joiner);
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
::Kokkos::parallel_reduce(label,
|
||||||
|
RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
functor_type(first, reducer, transformer), reducer);
|
||||||
|
|
||||||
|
// fence not needed since reducing into scalar
|
||||||
|
|
||||||
|
// as per standard, transform is not applied to the init value
|
||||||
|
// https://en.cppreference.com/w/cpp/algorithm/transform_reduce
|
||||||
|
return joiner(result.val, init_reduction_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||||
|
class ValueType, class JoinerType, class BinaryTransformerType>
|
||||||
|
ValueType transform_reduce_custom_functors_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex, IteratorType1 first1,
|
||||||
|
IteratorType1 last1, IteratorType2 first2, ValueType init_reduction_value,
|
||||||
|
JoinerType joiner, BinaryTransformerType transformer) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first1, first2);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first1, first2);
|
||||||
|
Impl::expect_valid_range(first1, last1);
|
||||||
|
|
||||||
|
if (first1 == last1) {
|
||||||
|
// init is returned, unmodified
|
||||||
|
return init_reduction_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using index_type = typename IteratorType1::difference_type;
|
||||||
|
using reducer_type =
|
||||||
|
ReducerWithArbitraryJoinerNoNeutralElement<ValueType, JoinerType>;
|
||||||
|
using functor_type =
|
||||||
|
StdTransformReduceTwoIntervalsFunctor<index_type, IteratorType1,
|
||||||
|
IteratorType2, reducer_type,
|
||||||
|
BinaryTransformerType>;
|
||||||
|
using reduction_value_type = typename reducer_type::value_type;
|
||||||
|
|
||||||
|
// run
|
||||||
|
reduction_value_type result;
|
||||||
|
reducer_type reducer(result, joiner);
|
||||||
|
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first1, last1);
|
||||||
|
::Kokkos::parallel_reduce(
|
||||||
|
label, RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
functor_type(first1, first2, reducer, transformer), reducer);
|
||||||
|
|
||||||
|
// fence not needed since reducing into scalar
|
||||||
|
return joiner(result.val, init_reduction_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||||
|
class ValueType>
|
||||||
|
ValueType transform_reduce_default_functors_impl(
|
||||||
|
const std::string& label, const ExecutionSpace& ex, IteratorType1 first1,
|
||||||
|
IteratorType1 last1, IteratorType2 first2, ValueType init_reduction_value) {
|
||||||
|
// checks
|
||||||
|
Impl::static_assert_random_access_and_accessible(ex, first1, first2);
|
||||||
|
Impl::static_assert_is_not_openmptarget(ex);
|
||||||
|
Impl::static_assert_iterators_have_matching_difference_type(first1, first2);
|
||||||
|
Impl::expect_valid_range(first1, last1);
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
using transformer_type =
|
||||||
|
Impl::StdTranformReduceDefaultBinaryTransformFunctor<ValueType>;
|
||||||
|
using joiner_type = Impl::StdTranformReduceDefaultJoinFunctor<ValueType>;
|
||||||
|
|
||||||
|
return transform_reduce_custom_functors_impl(
|
||||||
|
label, ex, first1, last1, first2, std::move(init_reduction_value),
|
||||||
|
joiner_type(), transformer_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Impl
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
//
|
||||||
|
// transform_reduce public API
|
||||||
|
//
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
// ----------------------------
|
||||||
|
// overload set1:
|
||||||
|
// no custom functors passed, so equivalent to
|
||||||
|
// transform_reduce(first1, last1, first2, init, plus<>(), multiplies<>());
|
||||||
|
// ----------------------------
|
||||||
|
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||||
|
class ValueType>
|
||||||
|
ValueType transform_reduce(const ExecutionSpace& ex, IteratorType1 first1,
|
||||||
|
IteratorType1 last1, IteratorType2 first2,
|
||||||
|
ValueType init_reduction_value) {
|
||||||
|
return Impl::transform_reduce_default_functors_impl(
|
||||||
|
"Kokkos::transform_reduce_default_functors_iterator_api", ex, first1,
|
||||||
|
last1, first2, std::move(init_reduction_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||||
|
class ValueType>
|
||||||
|
ValueType transform_reduce(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType1 first1, IteratorType1 last1,
|
||||||
|
IteratorType2 first2,
|
||||||
|
ValueType init_reduction_value) {
|
||||||
|
return Impl::transform_reduce_default_functors_impl(
|
||||||
|
label, ex, first1, last1, first2, std::move(init_reduction_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// overload1 accepting views
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType>
|
||||||
|
ValueType transform_reduce(
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& first_view,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& second_view,
|
||||||
|
ValueType init_reduction_value) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(first_view);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(second_view);
|
||||||
|
|
||||||
|
return Impl::transform_reduce_default_functors_impl(
|
||||||
|
"Kokkos::transform_reduce_default_functors_iterator_api", ex,
|
||||||
|
KE::cbegin(first_view), KE::cend(first_view), KE::cbegin(second_view),
|
||||||
|
std::move(init_reduction_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType>
|
||||||
|
ValueType transform_reduce(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& first_view,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& second_view,
|
||||||
|
ValueType init_reduction_value) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(first_view);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(second_view);
|
||||||
|
|
||||||
|
return Impl::transform_reduce_default_functors_impl(
|
||||||
|
label, ex, KE::cbegin(first_view), KE::cend(first_view),
|
||||||
|
KE::cbegin(second_view), std::move(init_reduction_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// overload set2:
|
||||||
|
// accepts a custom transform and joiner functor
|
||||||
|
//
|
||||||
|
|
||||||
|
// Note the std refers to the arg BinaryReductionOp
|
||||||
|
// but in the Kokkos naming convention, it corresponds
|
||||||
|
// to a "joiner" that knows how to join two values
|
||||||
|
// NOTE: "joiner/transformer" need to be commutative.
|
||||||
|
|
||||||
|
// https://en.cppreference.com/w/cpp/algorithm/transform_reduce
|
||||||
|
|
||||||
|
// api accepting iterators
|
||||||
|
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||||
|
class ValueType, class BinaryJoinerType, class BinaryTransform>
|
||||||
|
ValueType transform_reduce(const ExecutionSpace& ex, IteratorType1 first1,
|
||||||
|
IteratorType1 last1, IteratorType2 first2,
|
||||||
|
ValueType init_reduction_value,
|
||||||
|
BinaryJoinerType joiner,
|
||||||
|
BinaryTransform transformer) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
return Impl::transform_reduce_custom_functors_impl(
|
||||||
|
"Kokkos::transform_reduce_custom_functors_iterator_api", ex, first1,
|
||||||
|
last1, first2, std::move(init_reduction_value), std::move(joiner),
|
||||||
|
std::move(transformer));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType1, class IteratorType2,
|
||||||
|
class ValueType, class BinaryJoinerType, class BinaryTransform>
|
||||||
|
ValueType transform_reduce(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType1 first1, IteratorType1 last1,
|
||||||
|
IteratorType2 first2, ValueType init_reduction_value,
|
||||||
|
BinaryJoinerType joiner,
|
||||||
|
BinaryTransform transformer) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
return Impl::transform_reduce_custom_functors_impl(
|
||||||
|
label, ex, first1, last1, first2, std::move(init_reduction_value),
|
||||||
|
std::move(joiner), std::move(transformer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// accepting views
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType,
|
||||||
|
class BinaryJoinerType, class BinaryTransform>
|
||||||
|
ValueType transform_reduce(
|
||||||
|
const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& first_view,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& second_view,
|
||||||
|
ValueType init_reduction_value, BinaryJoinerType joiner,
|
||||||
|
BinaryTransform transformer) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(first_view);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(second_view);
|
||||||
|
|
||||||
|
return Impl::transform_reduce_custom_functors_impl(
|
||||||
|
"Kokkos::transform_reduce_custom_functors_view_api", ex,
|
||||||
|
KE::cbegin(first_view), KE::cend(first_view), KE::cbegin(second_view),
|
||||||
|
std::move(init_reduction_value), std::move(joiner),
|
||||||
|
std::move(transformer));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType1, class... Properties1,
|
||||||
|
class DataType2, class... Properties2, class ValueType,
|
||||||
|
class BinaryJoinerType, class BinaryTransform>
|
||||||
|
ValueType transform_reduce(
|
||||||
|
const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType1, Properties1...>& first_view,
|
||||||
|
const ::Kokkos::View<DataType2, Properties2...>& second_view,
|
||||||
|
ValueType init_reduction_value, BinaryJoinerType joiner,
|
||||||
|
BinaryTransform transformer) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(first_view);
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(second_view);
|
||||||
|
|
||||||
|
return Impl::transform_reduce_custom_functors_impl(
|
||||||
|
label, ex, KE::cbegin(first_view), KE::cend(first_view),
|
||||||
|
KE::cbegin(second_view), std::move(init_reduction_value),
|
||||||
|
std::move(joiner), std::move(transformer));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// overload set3:
|
||||||
|
//
|
||||||
|
// accepting iterators
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||||
|
class BinaryJoinerType, class UnaryTransform>
|
||||||
|
// need this to avoid ambiguous call
|
||||||
|
std::enable_if_t<
|
||||||
|
::Kokkos::Experimental::Impl::are_iterators<IteratorType>::value, ValueType>
|
||||||
|
transform_reduce(const ExecutionSpace& ex, IteratorType first1,
|
||||||
|
IteratorType last1, ValueType init_reduction_value,
|
||||||
|
BinaryJoinerType joiner, UnaryTransform transformer) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
return Impl::transform_reduce_custom_functors_impl(
|
||||||
|
"Kokkos::transform_reduce_custom_functors_iterator_api", ex, first1,
|
||||||
|
last1, std::move(init_reduction_value), std::move(joiner),
|
||||||
|
std::move(transformer));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType, class ValueType,
|
||||||
|
class BinaryJoinerType, class UnaryTransform>
|
||||||
|
// need this to avoid ambiguous call
|
||||||
|
std::enable_if_t<
|
||||||
|
::Kokkos::Experimental::Impl::are_iterators<IteratorType>::value, ValueType>
|
||||||
|
transform_reduce(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
IteratorType first1, IteratorType last1,
|
||||||
|
ValueType init_reduction_value, BinaryJoinerType joiner,
|
||||||
|
UnaryTransform transformer) {
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
return Impl::transform_reduce_custom_functors_impl(
|
||||||
|
label, ex, first1, last1, std::move(init_reduction_value),
|
||||||
|
std::move(joiner), std::move(transformer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// accepting views
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ValueType, class BinaryJoinerType, class UnaryTransform>
|
||||||
|
ValueType transform_reduce(const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ValueType init_reduction_value,
|
||||||
|
BinaryJoinerType joiner,
|
||||||
|
UnaryTransform transformer) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
return Impl::transform_reduce_custom_functors_impl(
|
||||||
|
"Kokkos::transform_reduce_custom_functors_view_api", ex, KE::cbegin(view),
|
||||||
|
KE::cend(view), std::move(init_reduction_value), std::move(joiner),
|
||||||
|
std::move(transformer));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class DataType, class... Properties,
|
||||||
|
class ValueType, class BinaryJoinerType, class UnaryTransform>
|
||||||
|
ValueType transform_reduce(const std::string& label, const ExecutionSpace& ex,
|
||||||
|
const ::Kokkos::View<DataType, Properties...>& view,
|
||||||
|
ValueType init_reduction_value,
|
||||||
|
BinaryJoinerType joiner,
|
||||||
|
UnaryTransform transformer) {
|
||||||
|
namespace KE = ::Kokkos::Experimental;
|
||||||
|
static_assert(std::is_move_constructible<ValueType>::value,
|
||||||
|
"ValueType must be move constructible.");
|
||||||
|
|
||||||
|
Impl::static_assert_is_admissible_to_kokkos_std_algorithms(view);
|
||||||
|
|
||||||
|
return Impl::transform_reduce_custom_functors_impl(
|
||||||
|
label, ex, KE::cbegin(view), KE::cend(view),
|
||||||
|
std::move(init_reduction_value), std::move(joiner),
|
||||||
|
std::move(transformer));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Experimental
|
||||||
|
} // namespace Kokkos
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -6,55 +6,29 @@ KOKKOS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../src )
|
|||||||
KOKKOS_INCLUDE_DIRECTORIES(${KOKKOS_SOURCE_DIR}/core/unit_test/category_files)
|
KOKKOS_INCLUDE_DIRECTORIES(${KOKKOS_SOURCE_DIR}/core/unit_test/category_files)
|
||||||
|
|
||||||
|
|
||||||
SET(GTEST_SOURCE_DIR ${${PARENT_PACKAGE_NAME}_SOURCE_DIR}/tpls/gtest)
|
|
||||||
KOKKOS_INCLUDE_DIRECTORIES(${GTEST_SOURCE_DIR})
|
|
||||||
|
|
||||||
# mfh 03 Nov 2017: The gtest library used here must have a different
|
|
||||||
# name than that of the gtest library built in KokkosCore. We can't
|
|
||||||
# just refer to the library in KokkosCore's tests, because it's
|
|
||||||
# possible to build only (e.g.,) KokkosAlgorithms tests, without
|
|
||||||
# building KokkosCore tests.
|
|
||||||
|
|
||||||
|
|
||||||
KOKKOS_ADD_TEST_LIBRARY(
|
|
||||||
kokkosalgorithms_gtest
|
|
||||||
HEADERS ${GTEST_SOURCE_DIR}/gtest/gtest.h
|
|
||||||
SOURCES ${GTEST_SOURCE_DIR}/gtest/gtest-all.cc
|
|
||||||
)
|
|
||||||
|
|
||||||
# avoid deprecation warnings from MSVC
|
|
||||||
TARGET_COMPILE_DEFINITIONS(kokkosalgorithms_gtest PUBLIC GTEST_HAS_TR1_TUPLE=0 GTEST_HAS_PTHREAD=0)
|
|
||||||
|
|
||||||
IF((NOT (Kokkos_ENABLE_CUDA AND WIN32)) AND (NOT ("${KOKKOS_CXX_COMPILER_ID}" STREQUAL "Fujitsu")))
|
|
||||||
TARGET_COMPILE_FEATURES(kokkosalgorithms_gtest PUBLIC cxx_std_14)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# Suppress clang-tidy diagnostics on code that we do not have control over
|
|
||||||
IF(CMAKE_CXX_CLANG_TIDY)
|
|
||||||
SET_TARGET_PROPERTIES(kokkosalgorithms_gtest PROPERTIES CXX_CLANG_TIDY "")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
SET(ALGORITHM UnitTestMain.cpp)
|
SET(ALGORITHM UnitTestMain.cpp)
|
||||||
|
|
||||||
IF(Kokkos_ENABLE_OPENMP)
|
foreach(Tag Threads;Serial;OpenMP;Cuda;HPX;HIP;SYCL;OpenMPTarget)
|
||||||
LIST(APPEND ALGORITHM_SOURCES
|
string(TOUPPER ${Tag} DEVICE)
|
||||||
|
string(TOLOWER ${Tag} dir)
|
||||||
|
|
||||||
|
if(Kokkos_ENABLE_${DEVICE})
|
||||||
|
set(dir ${CMAKE_CURRENT_BINARY_DIR}/${dir})
|
||||||
|
file(MAKE_DIRECTORY ${dir})
|
||||||
|
|
||||||
|
# -------------------------
|
||||||
|
# Sort1d,3d, Random
|
||||||
|
# -------------------------
|
||||||
|
set(SOURCES_A)
|
||||||
|
if(Tag STREQUAL "OpenMP")
|
||||||
|
LIST(APPEND SOURCES_A
|
||||||
TestOpenMP_Sort1D.cpp
|
TestOpenMP_Sort1D.cpp
|
||||||
TestOpenMP_Sort3D.cpp
|
TestOpenMP_Sort3D.cpp
|
||||||
TestOpenMP_SortDynamicView.cpp
|
TestOpenMP_SortDynamicView.cpp
|
||||||
)
|
)
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
foreach(Tag Threads;Serial;OpenMP;Cuda;HPX;HIP;SYCL;OpenMPTarget)
|
|
||||||
# Because there is always an exception to the rule
|
|
||||||
if(Tag STREQUAL "Threads")
|
|
||||||
set(DEVICE "PTHREAD")
|
|
||||||
else()
|
|
||||||
string(TOUPPER ${Tag} DEVICE)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(Kokkos_ENABLE_${DEVICE})
|
set(file ${dir}/TestRandomAndSort.cpp)
|
||||||
set(dir ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
set(file ${dir}/Test${Tag}.cpp)
|
|
||||||
# Write to a temporary intermediate file and call configure_file to avoid
|
# Write to a temporary intermediate file and call configure_file to avoid
|
||||||
# updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
|
# updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
|
||||||
file(WRITE ${dir}/dummy.cpp
|
file(WRITE ${dir}/dummy.cpp
|
||||||
@ -63,13 +37,122 @@ foreach(Tag Threads;Serial;OpenMP;Cuda;HPX;HIP;SYCL;OpenMPTarget)
|
|||||||
"#include <TestSortCommon.hpp>\n"
|
"#include <TestSortCommon.hpp>\n"
|
||||||
)
|
)
|
||||||
configure_file(${dir}/dummy.cpp ${file})
|
configure_file(${dir}/dummy.cpp ${file})
|
||||||
list(APPEND ALGORITHM_SOURCES ${file})
|
list(APPEND SOURCES_A ${file})
|
||||||
|
|
||||||
|
# ------------------------------------------
|
||||||
|
# std set A
|
||||||
|
# ------------------------------------------
|
||||||
|
set(STDALGO_SOURCES_A)
|
||||||
|
foreach(Name
|
||||||
|
StdReducers
|
||||||
|
StdAlgorithmsConstraints
|
||||||
|
RandomAccessIterator
|
||||||
|
)
|
||||||
|
list(APPEND STDALGO_SOURCES_A Test${Name}.cpp)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# ------------------------------------------
|
||||||
|
# std set B
|
||||||
|
# ------------------------------------------
|
||||||
|
set(STDALGO_SOURCES_B)
|
||||||
|
foreach(Name
|
||||||
|
StdAlgorithmsCommon
|
||||||
|
StdAlgorithmsMinMaxElementOps
|
||||||
|
)
|
||||||
|
list(APPEND STDALGO_SOURCES_B Test${Name}.cpp)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# ------------------------------------------
|
||||||
|
# std set C
|
||||||
|
# ------------------------------------------
|
||||||
|
set(STDALGO_SOURCES_C)
|
||||||
|
foreach(Name
|
||||||
|
StdAlgorithmsCommon
|
||||||
|
StdAlgorithmsLexicographicalCompare
|
||||||
|
StdAlgorithmsForEach
|
||||||
|
StdAlgorithmsFind
|
||||||
|
StdAlgorithmsFindFirstOf
|
||||||
|
StdAlgorithmsFindEnd
|
||||||
|
StdAlgorithmsCount
|
||||||
|
StdAlgorithmsEqual
|
||||||
|
StdAlgorithmsAllAnyNoneOf
|
||||||
|
StdAlgorithmsAdjacentFind
|
||||||
|
StdAlgorithmsSearch
|
||||||
|
StdAlgorithmsSearch_n
|
||||||
|
StdAlgorithmsMismatch
|
||||||
|
)
|
||||||
|
list(APPEND STDALGO_SOURCES_C Test${Name}.cpp)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# ------------------------------------------
|
||||||
|
# std set D
|
||||||
|
# ------------------------------------------
|
||||||
|
set(STDALGO_SOURCES_D)
|
||||||
|
foreach(Name
|
||||||
|
StdAlgorithmsCommon
|
||||||
|
StdAlgorithmsModOps
|
||||||
|
StdAlgorithmsModSeqOps
|
||||||
|
StdAlgorithmsReplace
|
||||||
|
StdAlgorithmsReplaceIf
|
||||||
|
StdAlgorithmsReplaceCopy
|
||||||
|
StdAlgorithmsReplaceCopyIf
|
||||||
|
StdAlgorithmsCopyIf
|
||||||
|
StdAlgorithmsUnique
|
||||||
|
StdAlgorithmsUniqueCopy
|
||||||
|
StdAlgorithmsRemove
|
||||||
|
StdAlgorithmsRemoveIf
|
||||||
|
StdAlgorithmsRemoveCopy
|
||||||
|
StdAlgorithmsRemoveCopyIf
|
||||||
|
StdAlgorithmsRotate
|
||||||
|
StdAlgorithmsRotateCopy
|
||||||
|
StdAlgorithmsReverse
|
||||||
|
StdAlgorithmsShiftLeft
|
||||||
|
StdAlgorithmsShiftRight
|
||||||
|
)
|
||||||
|
list(APPEND STDALGO_SOURCES_D Test${Name}.cpp)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# ------------------------------------------
|
||||||
|
# std set E
|
||||||
|
# ------------------------------------------
|
||||||
|
set(STDALGO_SOURCES_E)
|
||||||
|
foreach(Name
|
||||||
|
StdAlgorithmsCommon
|
||||||
|
StdAlgorithmsIsSorted
|
||||||
|
StdAlgorithmsIsSortedUntil
|
||||||
|
StdAlgorithmsPartitioningOps
|
||||||
|
StdAlgorithmsPartitionCopy
|
||||||
|
StdAlgorithmsNumerics
|
||||||
|
StdAlgorithmsAdjacentDifference
|
||||||
|
StdAlgorithmsExclusiveScan
|
||||||
|
StdAlgorithmsInclusiveScan
|
||||||
|
StdAlgorithmsTransformUnaryOp
|
||||||
|
StdAlgorithmsTransformExclusiveScan
|
||||||
|
StdAlgorithmsTransformInclusiveScan
|
||||||
|
)
|
||||||
|
list(APPEND STDALGO_SOURCES_E Test${Name}.cpp)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
KOKKOS_ADD_EXECUTABLE_AND_TEST(
|
KOKKOS_ADD_EXECUTABLE_AND_TEST(
|
||||||
UnitTest
|
UnitTest_RandomAndSort
|
||||||
SOURCES
|
SOURCES
|
||||||
UnitTestMain.cpp
|
UnitTestMain.cpp
|
||||||
${ALGORITHM_SOURCES}
|
${SOURCES_A}
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(ID A;B;C;D;E)
|
||||||
|
KOKKOS_ADD_EXECUTABLE_AND_TEST(
|
||||||
|
UnitTest_StdSet_${ID}
|
||||||
|
SOURCES
|
||||||
|
UnitTestMain.cpp
|
||||||
|
${STDALGO_SOURCES_${ID}}
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
KOKKOS_ADD_EXECUTABLE(
|
||||||
|
UnitTest_StdAlgoCompileOnly
|
||||||
|
SOURCES TestStdAlgorithmsCompileOnly.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@ -45,7 +45,7 @@ ifeq ($(KOKKOS_INTERNAL_USE_HIP), 1)
|
|||||||
TEST_TARGETS += test-hip
|
TEST_TARGETS += test-hip
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
|
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
|
||||||
OBJ_THREADS = TestThreads.o UnitTestMain.o gtest-all.o
|
OBJ_THREADS = TestThreads.o UnitTestMain.o gtest-all.o
|
||||||
TARGETS += KokkosAlgorithms_UnitTest_Threads
|
TARGETS += KokkosAlgorithms_UnitTest_Threads
|
||||||
TEST_TARGETS += test-threads
|
TEST_TARGETS += test-threads
|
||||||
|
|||||||
@ -47,6 +47,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <Kokkos_DynRankView.hpp>
|
||||||
#include <Kokkos_Timer.hpp>
|
#include <Kokkos_Timer.hpp>
|
||||||
#include <Kokkos_Core.hpp>
|
#include <Kokkos_Core.hpp>
|
||||||
#include <Kokkos_Random.hpp>
|
#include <Kokkos_Random.hpp>
|
||||||
@ -327,10 +328,6 @@ template <class RandomGenerator, class Scalar>
|
|||||||
struct test_random_scalar {
|
struct test_random_scalar {
|
||||||
using rnd_type = typename RandomGenerator::generator_type;
|
using rnd_type = typename RandomGenerator::generator_type;
|
||||||
|
|
||||||
int pass_mean, pass_var, pass_covar;
|
|
||||||
int pass_hist1d_mean, pass_hist1d_var, pass_hist1d_covar;
|
|
||||||
int pass_hist3d_mean, pass_hist3d_var, pass_hist3d_covar;
|
|
||||||
|
|
||||||
test_random_scalar(
|
test_random_scalar(
|
||||||
typename test_random_functor<RandomGenerator, int>::type_1d& density_1d,
|
typename test_random_functor<RandomGenerator, int>::type_1d& density_1d,
|
||||||
typename test_random_functor<RandomGenerator, int>::type_3d& density_3d,
|
typename test_random_functor<RandomGenerator, int>::type_3d& density_3d,
|
||||||
@ -357,18 +354,15 @@ struct test_random_scalar {
|
|||||||
variance_expect / (result.variance / num_draws / 3) - 1.0;
|
variance_expect / (result.variance / num_draws / 3) - 1.0;
|
||||||
double covariance_eps =
|
double covariance_eps =
|
||||||
result.covariance / num_draws / 2 / variance_expect;
|
result.covariance / num_draws / 2 / variance_expect;
|
||||||
pass_mean = ((-tolerance < mean_eps) && (tolerance > mean_eps)) ? 1 : 0;
|
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||||
pass_var = ((-1.5 * tolerance < variance_eps) &&
|
if (!std::is_same<Scalar, Kokkos::Experimental::bhalf_t>::value) {
|
||||||
(1.5 * tolerance > variance_eps))
|
#endif
|
||||||
? 1
|
EXPECT_LT(std::abs(mean_eps), tolerance);
|
||||||
: 0;
|
EXPECT_LT(std::abs(variance_eps), 1.5 * tolerance);
|
||||||
pass_covar = ((-2.0 * tolerance < covariance_eps) &&
|
EXPECT_LT(std::abs(covariance_eps), 2.0 * tolerance);
|
||||||
(2.0 * tolerance > covariance_eps))
|
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||||
? 1
|
}
|
||||||
: 0;
|
#endif
|
||||||
cout << "Pass: " << pass_mean << " " << pass_var << " " << mean_eps << " "
|
|
||||||
<< variance_eps << " " << covariance_eps << " || " << tolerance
|
|
||||||
<< endl;
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cout << " -- Testing 1-D histogram" << endl;
|
cout << " -- Testing 1-D histogram" << endl;
|
||||||
@ -399,17 +393,15 @@ struct test_random_scalar {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pass_hist1d_mean =
|
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||||
((-mean_eps_expect < mean_eps) && (mean_eps_expect > mean_eps)) ? 1
|
if (!std::is_same<Scalar, Kokkos::Experimental::bhalf_t>::value) {
|
||||||
: 0;
|
#endif
|
||||||
pass_hist1d_var = ((-variance_eps_expect < variance_eps) &&
|
EXPECT_LT(std::abs(mean_eps), mean_eps_expect);
|
||||||
(variance_eps_expect > variance_eps))
|
EXPECT_LT(std::abs(variance_eps), variance_eps_expect);
|
||||||
? 1
|
EXPECT_LT(std::abs(covariance_eps), covariance_eps_expect);
|
||||||
: 0;
|
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||||
pass_hist1d_covar = ((-covariance_eps_expect < covariance_eps) &&
|
}
|
||||||
(covariance_eps_expect > covariance_eps))
|
#endif
|
||||||
? 1
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
cout << "Density 1D: " << mean_eps << " " << variance_eps << " "
|
cout << "Density 1D: " << mean_eps << " " << variance_eps << " "
|
||||||
<< (result.covariance / HIST_DIM1D / HIST_DIM1D) << " || "
|
<< (result.covariance / HIST_DIM1D / HIST_DIM1D) << " || "
|
||||||
@ -445,16 +437,15 @@ struct test_random_scalar {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pass_hist3d_mean =
|
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||||
((-tolerance < mean_eps) && (tolerance > mean_eps)) ? 1 : 0;
|
if (!std::is_same<Scalar, Kokkos::Experimental::bhalf_t>::value) {
|
||||||
pass_hist3d_var = ((-variance_factor * tolerance < variance_eps) &&
|
#endif
|
||||||
(variance_factor * tolerance > variance_eps))
|
EXPECT_LT(std::abs(mean_eps), tolerance);
|
||||||
? 1
|
EXPECT_LT(std::abs(variance_eps), variance_factor);
|
||||||
: 0;
|
EXPECT_LT(std::abs(covariance_eps), variance_factor);
|
||||||
pass_hist3d_covar = ((-variance_factor * tolerance < covariance_eps) &&
|
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
|
||||||
(variance_factor * tolerance > covariance_eps))
|
}
|
||||||
? 1
|
#endif
|
||||||
: 0;
|
|
||||||
|
|
||||||
cout << "Density 3D: " << mean_eps << " " << variance_eps << " "
|
cout << "Density 3D: " << mean_eps << " " << variance_eps << " "
|
||||||
<< result.covariance / HIST_DIM1D / HIST_DIM1D << " || " << tolerance
|
<< result.covariance / HIST_DIM1D / HIST_DIM1D << " || " << tolerance
|
||||||
@ -479,106 +470,79 @@ void test_random(unsigned int num_draws) {
|
|||||||
cout << "Test Scalar=int" << endl;
|
cout << "Test Scalar=int" << endl;
|
||||||
test_random_scalar<RandomGenerator, int> test_int(density_1d, density_3d,
|
test_random_scalar<RandomGenerator, int> test_int(density_1d, density_3d,
|
||||||
pool, num_draws);
|
pool, num_draws);
|
||||||
ASSERT_EQ(test_int.pass_mean, 1);
|
|
||||||
ASSERT_EQ(test_int.pass_var, 1);
|
|
||||||
ASSERT_EQ(test_int.pass_covar, 1);
|
|
||||||
ASSERT_EQ(test_int.pass_hist1d_mean, 1);
|
|
||||||
ASSERT_EQ(test_int.pass_hist1d_var, 1);
|
|
||||||
ASSERT_EQ(test_int.pass_hist1d_covar, 1);
|
|
||||||
ASSERT_EQ(test_int.pass_hist3d_mean, 1);
|
|
||||||
ASSERT_EQ(test_int.pass_hist3d_var, 1);
|
|
||||||
ASSERT_EQ(test_int.pass_hist3d_covar, 1);
|
|
||||||
deep_copy(density_1d, 0);
|
deep_copy(density_1d, 0);
|
||||||
deep_copy(density_3d, 0);
|
deep_copy(density_3d, 0);
|
||||||
|
|
||||||
cout << "Test Scalar=unsigned int" << endl;
|
cout << "Test Scalar=unsigned int" << endl;
|
||||||
test_random_scalar<RandomGenerator, unsigned int> test_uint(
|
test_random_scalar<RandomGenerator, unsigned int> test_uint(
|
||||||
density_1d, density_3d, pool, num_draws);
|
density_1d, density_3d, pool, num_draws);
|
||||||
ASSERT_EQ(test_uint.pass_mean, 1);
|
|
||||||
ASSERT_EQ(test_uint.pass_var, 1);
|
|
||||||
ASSERT_EQ(test_uint.pass_covar, 1);
|
|
||||||
ASSERT_EQ(test_uint.pass_hist1d_mean, 1);
|
|
||||||
ASSERT_EQ(test_uint.pass_hist1d_var, 1);
|
|
||||||
ASSERT_EQ(test_uint.pass_hist1d_covar, 1);
|
|
||||||
ASSERT_EQ(test_uint.pass_hist3d_mean, 1);
|
|
||||||
ASSERT_EQ(test_uint.pass_hist3d_var, 1);
|
|
||||||
ASSERT_EQ(test_uint.pass_hist3d_covar, 1);
|
|
||||||
deep_copy(density_1d, 0);
|
deep_copy(density_1d, 0);
|
||||||
deep_copy(density_3d, 0);
|
deep_copy(density_3d, 0);
|
||||||
|
|
||||||
cout << "Test Scalar=int64_t" << endl;
|
cout << "Test Scalar=int64_t" << endl;
|
||||||
test_random_scalar<RandomGenerator, int64_t> test_int64(
|
test_random_scalar<RandomGenerator, int64_t> test_int64(
|
||||||
density_1d, density_3d, pool, num_draws);
|
density_1d, density_3d, pool, num_draws);
|
||||||
ASSERT_EQ(test_int64.pass_mean, 1);
|
|
||||||
ASSERT_EQ(test_int64.pass_var, 1);
|
|
||||||
ASSERT_EQ(test_int64.pass_covar, 1);
|
|
||||||
ASSERT_EQ(test_int64.pass_hist1d_mean, 1);
|
|
||||||
ASSERT_EQ(test_int64.pass_hist1d_var, 1);
|
|
||||||
ASSERT_EQ(test_int64.pass_hist1d_covar, 1);
|
|
||||||
ASSERT_EQ(test_int64.pass_hist3d_mean, 1);
|
|
||||||
ASSERT_EQ(test_int64.pass_hist3d_var, 1);
|
|
||||||
ASSERT_EQ(test_int64.pass_hist3d_covar, 1);
|
|
||||||
deep_copy(density_1d, 0);
|
deep_copy(density_1d, 0);
|
||||||
deep_copy(density_3d, 0);
|
deep_copy(density_3d, 0);
|
||||||
|
|
||||||
cout << "Test Scalar=uint64_t" << endl;
|
cout << "Test Scalar=uint64_t" << endl;
|
||||||
test_random_scalar<RandomGenerator, uint64_t> test_uint64(
|
test_random_scalar<RandomGenerator, uint64_t> test_uint64(
|
||||||
density_1d, density_3d, pool, num_draws);
|
density_1d, density_3d, pool, num_draws);
|
||||||
ASSERT_EQ(test_uint64.pass_mean, 1);
|
|
||||||
ASSERT_EQ(test_uint64.pass_var, 1);
|
|
||||||
ASSERT_EQ(test_uint64.pass_covar, 1);
|
|
||||||
ASSERT_EQ(test_uint64.pass_hist1d_mean, 1);
|
|
||||||
ASSERT_EQ(test_uint64.pass_hist1d_var, 1);
|
|
||||||
ASSERT_EQ(test_uint64.pass_hist1d_covar, 1);
|
|
||||||
ASSERT_EQ(test_uint64.pass_hist3d_mean, 1);
|
|
||||||
ASSERT_EQ(test_uint64.pass_hist3d_var, 1);
|
|
||||||
ASSERT_EQ(test_uint64.pass_hist3d_covar, 1);
|
|
||||||
deep_copy(density_1d, 0);
|
deep_copy(density_1d, 0);
|
||||||
deep_copy(density_3d, 0);
|
deep_copy(density_3d, 0);
|
||||||
|
|
||||||
cout << "Test Scalar=half" << endl;
|
cout << "Test Scalar=half" << endl;
|
||||||
test_random_scalar<RandomGenerator, Kokkos::Experimental::half_t> test_half(
|
test_random_scalar<RandomGenerator, Kokkos::Experimental::half_t> test_half(
|
||||||
density_1d, density_3d, pool, num_draws);
|
density_1d, density_3d, pool, num_draws);
|
||||||
ASSERT_EQ(test_half.pass_mean, 1);
|
deep_copy(density_1d, 0);
|
||||||
ASSERT_EQ(test_half.pass_var, 1);
|
deep_copy(density_3d, 0);
|
||||||
ASSERT_EQ(test_half.pass_covar, 1);
|
|
||||||
ASSERT_EQ(test_half.pass_hist1d_mean, 1);
|
cout << "Test Scalar=bhalf" << endl;
|
||||||
ASSERT_EQ(test_half.pass_hist1d_var, 1);
|
test_random_scalar<RandomGenerator, Kokkos::Experimental::bhalf_t> test_bhalf(
|
||||||
ASSERT_EQ(test_half.pass_hist1d_covar, 1);
|
density_1d, density_3d, pool, num_draws);
|
||||||
ASSERT_EQ(test_half.pass_hist3d_mean, 1);
|
|
||||||
ASSERT_EQ(test_half.pass_hist3d_var, 1);
|
|
||||||
ASSERT_EQ(test_half.pass_hist3d_covar, 1);
|
|
||||||
deep_copy(density_1d, 0);
|
deep_copy(density_1d, 0);
|
||||||
deep_copy(density_3d, 0);
|
deep_copy(density_3d, 0);
|
||||||
|
|
||||||
cout << "Test Scalar=float" << endl;
|
cout << "Test Scalar=float" << endl;
|
||||||
test_random_scalar<RandomGenerator, float> test_float(density_1d, density_3d,
|
test_random_scalar<RandomGenerator, float> test_float(density_1d, density_3d,
|
||||||
pool, num_draws);
|
pool, num_draws);
|
||||||
ASSERT_EQ(test_float.pass_mean, 1);
|
|
||||||
ASSERT_EQ(test_float.pass_var, 1);
|
|
||||||
ASSERT_EQ(test_float.pass_covar, 1);
|
|
||||||
ASSERT_EQ(test_float.pass_hist1d_mean, 1);
|
|
||||||
ASSERT_EQ(test_float.pass_hist1d_var, 1);
|
|
||||||
ASSERT_EQ(test_float.pass_hist1d_covar, 1);
|
|
||||||
ASSERT_EQ(test_float.pass_hist3d_mean, 1);
|
|
||||||
ASSERT_EQ(test_float.pass_hist3d_var, 1);
|
|
||||||
ASSERT_EQ(test_float.pass_hist3d_covar, 1);
|
|
||||||
deep_copy(density_1d, 0);
|
deep_copy(density_1d, 0);
|
||||||
deep_copy(density_3d, 0);
|
deep_copy(density_3d, 0);
|
||||||
|
|
||||||
cout << "Test Scalar=double" << endl;
|
cout << "Test Scalar=double" << endl;
|
||||||
test_random_scalar<RandomGenerator, double> test_double(
|
test_random_scalar<RandomGenerator, double> test_double(
|
||||||
density_1d, density_3d, pool, num_draws);
|
density_1d, density_3d, pool, num_draws);
|
||||||
ASSERT_EQ(test_double.pass_mean, 1);
|
|
||||||
ASSERT_EQ(test_double.pass_var, 1);
|
|
||||||
ASSERT_EQ(test_double.pass_covar, 1);
|
|
||||||
ASSERT_EQ(test_double.pass_hist1d_mean, 1);
|
|
||||||
ASSERT_EQ(test_double.pass_hist1d_var, 1);
|
|
||||||
ASSERT_EQ(test_double.pass_hist1d_covar, 1);
|
|
||||||
ASSERT_EQ(test_double.pass_hist3d_mean, 1);
|
|
||||||
ASSERT_EQ(test_double.pass_hist3d_var, 1);
|
|
||||||
ASSERT_EQ(test_double.pass_hist3d_covar, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class Pool>
|
||||||
|
struct TestDynRankView {
|
||||||
|
using ReducerType = Kokkos::MinMax<double, Kokkos::HostSpace>;
|
||||||
|
using ReducerValueType = typename ReducerType::value_type;
|
||||||
|
|
||||||
|
Kokkos::DynRankView<double, ExecutionSpace> A;
|
||||||
|
|
||||||
|
TestDynRankView(int n) : A("a", n) {}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION void operator()(int i, ReducerValueType& update) const {
|
||||||
|
if (A(i) < update.min_val) update.min_val = A(i);
|
||||||
|
if (A(i) > update.max_val) update.max_val = A(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
Pool random(13);
|
||||||
|
double min = 10.;
|
||||||
|
double max = 100.;
|
||||||
|
Kokkos::fill_random(A, random, min, max);
|
||||||
|
|
||||||
|
ReducerValueType val;
|
||||||
|
Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecutionSpace>(0, A.size()),
|
||||||
|
*this, ReducerType(val));
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
ASSERT_GE(val.min_val, min);
|
||||||
|
ASSERT_LE(val.max_val, max);
|
||||||
|
}
|
||||||
|
};
|
||||||
} // namespace Impl
|
} // namespace Impl
|
||||||
|
|
||||||
template <typename ExecutionSpace>
|
template <typename ExecutionSpace>
|
||||||
@ -593,6 +557,9 @@ void test_random_xorshift64() {
|
|||||||
Impl::test_random<Kokkos::Random_XorShift64_Pool<
|
Impl::test_random<Kokkos::Random_XorShift64_Pool<
|
||||||
Kokkos::Device<ExecutionSpace, typename ExecutionSpace::memory_space>>>(
|
Kokkos::Device<ExecutionSpace, typename ExecutionSpace::memory_space>>>(
|
||||||
num_draws);
|
num_draws);
|
||||||
|
Impl::TestDynRankView<ExecutionSpace,
|
||||||
|
Kokkos::Random_XorShift64_Pool<ExecutionSpace>>(10000)
|
||||||
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ExecutionSpace>
|
template <typename ExecutionSpace>
|
||||||
@ -608,6 +575,9 @@ void test_random_xorshift1024() {
|
|||||||
Impl::test_random<Kokkos::Random_XorShift1024_Pool<
|
Impl::test_random<Kokkos::Random_XorShift1024_Pool<
|
||||||
Kokkos::Device<ExecutionSpace, typename ExecutionSpace::memory_space>>>(
|
Kokkos::Device<ExecutionSpace, typename ExecutionSpace::memory_space>>>(
|
||||||
num_draws);
|
num_draws);
|
||||||
|
Impl::TestDynRankView<ExecutionSpace,
|
||||||
|
Kokkos::Random_XorShift1024_Pool<ExecutionSpace>>(10000)
|
||||||
|
.run();
|
||||||
}
|
}
|
||||||
} // namespace Test
|
} // namespace Test
|
||||||
|
|
||||||
|
|||||||
252
lib/kokkos/algorithms/unit_tests/TestRandomAccessIterator.cpp
Normal file
252
lib/kokkos/algorithms/unit_tests/TestRandomAccessIterator.cpp
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_RandomAccessIterator.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_Distance.hpp>
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
struct random_access_iterator_test : std_algorithms_test {
|
||||||
|
public:
|
||||||
|
virtual void SetUp() {
|
||||||
|
Kokkos::parallel_for(m_static_view.extent(0),
|
||||||
|
AssignIndexFunctor<static_view_t>(m_static_view));
|
||||||
|
|
||||||
|
Kokkos::parallel_for(m_static_view.extent(0),
|
||||||
|
AssignIndexFunctor<dyn_view_t>(m_dynamic_view));
|
||||||
|
|
||||||
|
Kokkos::parallel_for(m_static_view.extent(0),
|
||||||
|
AssignIndexFunctor<strided_view_t>(m_strided_view));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(random_access_iterator_test, constructor) {
|
||||||
|
// just tests that constructor works
|
||||||
|
auto it1 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view);
|
||||||
|
auto it2 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view);
|
||||||
|
auto it3 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view);
|
||||||
|
auto it4 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 3);
|
||||||
|
auto it5 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view, 3);
|
||||||
|
auto it6 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view, 3);
|
||||||
|
EXPECT_TRUE(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class IteratorType, class ValueType>
|
||||||
|
void test_random_access_it_verify(IteratorType it, ValueType gold_value) {
|
||||||
|
using view_t = Kokkos::View<typename IteratorType::value_type>;
|
||||||
|
view_t checkView("checkView");
|
||||||
|
CopyFromIteratorFunctor<IteratorType, view_t> cf(it, checkView);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy", 1, cf);
|
||||||
|
auto v_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), checkView);
|
||||||
|
EXPECT_EQ(v_h(), gold_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(random_access_iterator_test, dereference) {
|
||||||
|
auto it1 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view);
|
||||||
|
auto it2 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view);
|
||||||
|
auto it3 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view);
|
||||||
|
test_random_access_it_verify(it1, (value_type)0);
|
||||||
|
test_random_access_it_verify(it2, (value_type)0);
|
||||||
|
test_random_access_it_verify(it3, (value_type)0);
|
||||||
|
|
||||||
|
auto it4 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 3);
|
||||||
|
auto it5 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view, 4);
|
||||||
|
auto it6 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view, 5);
|
||||||
|
test_random_access_it_verify(it4, (value_type)3);
|
||||||
|
test_random_access_it_verify(it5, (value_type)4);
|
||||||
|
test_random_access_it_verify(it6, (value_type)5);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ItTypeFrom, class ViewTypeTo>
|
||||||
|
struct CopyFromIteratorUsingSubscriptFunctor {
|
||||||
|
ItTypeFrom m_itFrom;
|
||||||
|
ViewTypeTo m_viewTo;
|
||||||
|
|
||||||
|
CopyFromIteratorUsingSubscriptFunctor(const ItTypeFrom itFromIn,
|
||||||
|
const ViewTypeTo viewToIn)
|
||||||
|
: m_itFrom(itFromIn), m_viewTo(viewToIn) {}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(int i) const { m_viewTo(i) = m_itFrom[i]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IteratorType>
|
||||||
|
void test_random_access_it_subscript_op_verify(IteratorType it) {
|
||||||
|
using value_t = typename IteratorType::value_type;
|
||||||
|
using view_t = Kokkos::View<value_t*>;
|
||||||
|
view_t checkView("checkView", 3);
|
||||||
|
CopyFromIteratorUsingSubscriptFunctor<IteratorType, view_t> cf(it, checkView);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy", 3, cf);
|
||||||
|
|
||||||
|
auto v_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), checkView);
|
||||||
|
EXPECT_EQ(v_h(0), (value_t)0);
|
||||||
|
EXPECT_EQ(v_h(1), (value_t)1);
|
||||||
|
EXPECT_EQ(v_h(2), (value_t)2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(random_access_iterator_test, subscript_operator) {
|
||||||
|
auto it1 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view);
|
||||||
|
auto it2 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view);
|
||||||
|
auto it3 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view);
|
||||||
|
test_random_access_it_subscript_op_verify(it1);
|
||||||
|
test_random_access_it_subscript_op_verify(it2);
|
||||||
|
test_random_access_it_subscript_op_verify(it3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(random_access_iterator_test, operatorsSet1) {
|
||||||
|
auto it1 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 3);
|
||||||
|
auto it2 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view, 3);
|
||||||
|
auto it3 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view, 3);
|
||||||
|
++it1;
|
||||||
|
++it2;
|
||||||
|
++it3;
|
||||||
|
test_random_access_it_verify(it1, (value_type)4);
|
||||||
|
test_random_access_it_verify(it2, (value_type)4);
|
||||||
|
test_random_access_it_verify(it3, (value_type)4);
|
||||||
|
|
||||||
|
--it1;
|
||||||
|
--it2;
|
||||||
|
--it3;
|
||||||
|
test_random_access_it_verify(it1, (value_type)3);
|
||||||
|
test_random_access_it_verify(it2, (value_type)3);
|
||||||
|
test_random_access_it_verify(it3, (value_type)3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(random_access_iterator_test, operatorsSet2) {
|
||||||
|
auto it1 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 3);
|
||||||
|
auto it2 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view, 3);
|
||||||
|
auto it3 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view, 3);
|
||||||
|
auto it11 = it1 + 3;
|
||||||
|
auto it21 = it2 + 3;
|
||||||
|
auto it31 = it3 + 3;
|
||||||
|
test_random_access_it_verify(it11, (value_type)6);
|
||||||
|
test_random_access_it_verify(it21, (value_type)6);
|
||||||
|
test_random_access_it_verify(it31, (value_type)6);
|
||||||
|
|
||||||
|
auto it12 = it11 - 4;
|
||||||
|
auto it22 = it21 - 4;
|
||||||
|
auto it32 = it31 - 4;
|
||||||
|
test_random_access_it_verify(it12, (value_type)2);
|
||||||
|
test_random_access_it_verify(it22, (value_type)2);
|
||||||
|
test_random_access_it_verify(it32, (value_type)2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(random_access_iterator_test, operatorsSet3) {
|
||||||
|
auto it1 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 3);
|
||||||
|
auto it2 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view, 3);
|
||||||
|
auto it3 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view, 3);
|
||||||
|
it1 += 3;
|
||||||
|
it2 += 3;
|
||||||
|
it3 += 3;
|
||||||
|
test_random_access_it_verify(it1, (value_type)6);
|
||||||
|
test_random_access_it_verify(it2, (value_type)6);
|
||||||
|
test_random_access_it_verify(it3, (value_type)6);
|
||||||
|
|
||||||
|
it1 -= 4;
|
||||||
|
it2 -= 4;
|
||||||
|
it3 -= 4;
|
||||||
|
test_random_access_it_verify(it1, (value_type)2);
|
||||||
|
test_random_access_it_verify(it2, (value_type)2);
|
||||||
|
test_random_access_it_verify(it3, (value_type)2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(random_access_iterator_test, operatorsSet4) {
|
||||||
|
auto it1 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 3);
|
||||||
|
auto it2 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view, 3);
|
||||||
|
auto it3 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view, 3);
|
||||||
|
|
||||||
|
auto it4 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 4);
|
||||||
|
auto it5 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view, 4);
|
||||||
|
auto it6 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view, 4);
|
||||||
|
EXPECT_TRUE(it1 != it4);
|
||||||
|
EXPECT_TRUE(it2 != it5);
|
||||||
|
EXPECT_TRUE(it3 != it6);
|
||||||
|
EXPECT_TRUE(it1 < it4);
|
||||||
|
EXPECT_TRUE(it2 < it5);
|
||||||
|
EXPECT_TRUE(it3 < it6);
|
||||||
|
EXPECT_TRUE(it1 <= it4);
|
||||||
|
EXPECT_TRUE(it2 <= it5);
|
||||||
|
EXPECT_TRUE(it3 <= it6);
|
||||||
|
|
||||||
|
auto it7 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 3);
|
||||||
|
auto it8 = KE::Impl::RandomAccessIterator<dyn_view_t>(m_dynamic_view, 3);
|
||||||
|
auto it9 = KE::Impl::RandomAccessIterator<strided_view_t>(m_strided_view, 3);
|
||||||
|
EXPECT_TRUE(it1 == it7);
|
||||||
|
EXPECT_TRUE(it2 == it8);
|
||||||
|
EXPECT_TRUE(it3 == it9);
|
||||||
|
EXPECT_TRUE(it1 >= it7);
|
||||||
|
EXPECT_TRUE(it2 >= it8);
|
||||||
|
EXPECT_TRUE(it3 >= it9);
|
||||||
|
EXPECT_TRUE(it4 > it7);
|
||||||
|
EXPECT_TRUE(it5 > it8);
|
||||||
|
EXPECT_TRUE(it6 > it9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(random_access_iterator_test, assignment_operator) {
|
||||||
|
auto it1 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 3);
|
||||||
|
auto it2 = KE::Impl::RandomAccessIterator<static_view_t>(m_static_view, 5);
|
||||||
|
EXPECT_NE(it1, it2);
|
||||||
|
|
||||||
|
it2 = it1;
|
||||||
|
EXPECT_EQ(it1, it2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(random_access_iterator_test, distance) {
|
||||||
|
auto first = KE::begin(m_dynamic_view);
|
||||||
|
auto last = KE::end(m_dynamic_view);
|
||||||
|
|
||||||
|
EXPECT_EQ(0, KE::distance(first, first));
|
||||||
|
EXPECT_EQ(1, KE::distance(first, first + 1));
|
||||||
|
EXPECT_EQ(m_dynamic_view.extent(0), size_t(KE::distance(first, last)));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -164,8 +164,8 @@ void test_1D_sort_impl(unsigned int n, bool force_kokkos) {
|
|||||||
unsigned int equal_sum =
|
unsigned int equal_sum =
|
||||||
(ratio > (1.0 - epsilon)) && (ratio < (1.0 + epsilon)) ? 1 : 0;
|
(ratio > (1.0 - epsilon)) && (ratio < (1.0 + epsilon)) ? 1 : 0;
|
||||||
|
|
||||||
ASSERT_EQ(sort_fails, 0);
|
ASSERT_EQ(sort_fails, 0u);
|
||||||
ASSERT_EQ(equal_sum, 1);
|
ASSERT_EQ(equal_sum, 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ExecutionSpace, typename KeyType>
|
template <class ExecutionSpace, typename KeyType>
|
||||||
@ -215,8 +215,8 @@ void test_3D_sort_impl(unsigned int n) {
|
|||||||
if (sort_fails)
|
if (sort_fails)
|
||||||
printf("3D Sort Sum: %f %f Fails: %u\n", sum_before, sum_after, sort_fails);
|
printf("3D Sort Sum: %f %f Fails: %u\n", sum_before, sum_after, sort_fails);
|
||||||
|
|
||||||
ASSERT_EQ(sort_fails, 0);
|
ASSERT_EQ(sort_fails, 0u);
|
||||||
ASSERT_EQ(equal_sum, 1);
|
ASSERT_EQ(equal_sum, 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -279,8 +279,8 @@ void test_dynamic_view_sort_impl(unsigned int n) {
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(sort_fails, 0);
|
ASSERT_EQ(sort_fails, 0u);
|
||||||
ASSERT_EQ(equal_sum, 1);
|
ASSERT_EQ(equal_sum, 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|||||||
@ -0,0 +1,293 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_Numeric.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace AdjacentDifference {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class DestViewType>
|
||||||
|
void fill_view(DestViewType dest_view, const std::string& name) {
|
||||||
|
// we need to be careful because dest_view might not be deep copyable
|
||||||
|
// for instance strided layout
|
||||||
|
|
||||||
|
using value_type = typename DestViewType::value_type;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
auto aux_view =
|
||||||
|
create_deep_copyable_compatible_view_with_same_extent(dest_view);
|
||||||
|
auto aux_v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element") {
|
||||||
|
aux_v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
aux_v_h(0) = static_cast<value_type>(1);
|
||||||
|
aux_v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
aux_v_h(0) = static_cast<value_type>(2);
|
||||||
|
aux_v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
aux_v_h(i) = static_cast<value_type>(i) * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
aux_v_h(i) = static_cast<value_type>(i) * 3;
|
||||||
|
}
|
||||||
|
aux_v_h(5) = static_cast<value_type>(-15);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
aux_v_h(i) = static_cast<value_type>(i) * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
aux_v_h(i) = static_cast<value_type>(i) * 2;
|
||||||
|
}
|
||||||
|
aux_v_h(4) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
aux_v_h(i) = static_cast<value_type>(-100) + static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
aux_v_h(i) = static_cast<value_type>(-100) + static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
aux_v_h(156) = static_cast<value_type>(-250);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, aux_v_h);
|
||||||
|
CopyFunctor<decltype(aux_view), DestViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TestViewType, class... Args>
|
||||||
|
auto compute_gold(TestViewType test_view, const std::string& name,
|
||||||
|
Args... args /* copy on purpose */) {
|
||||||
|
// we need to be careful because test_view might not be deep copyable
|
||||||
|
// for instance strided layout
|
||||||
|
|
||||||
|
const std::size_t ext = test_view.extent(0);
|
||||||
|
|
||||||
|
// create a deep copyable clone of test_view
|
||||||
|
auto test_view_dc = create_deep_copyable_compatible_clone(test_view);
|
||||||
|
auto test_view_dc_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), test_view_dc);
|
||||||
|
|
||||||
|
// create gold deep copyable view
|
||||||
|
auto gold_view =
|
||||||
|
create_deep_copyable_compatible_view_with_same_extent(test_view);
|
||||||
|
auto gold_view_h = create_mirror_view(Kokkos::HostSpace(), gold_view);
|
||||||
|
|
||||||
|
// compute gold solution on host and deep copy to device
|
||||||
|
if (name == "empty") {
|
||||||
|
return gold_view;
|
||||||
|
} else {
|
||||||
|
using value_type = typename TestViewType::value_type;
|
||||||
|
std::vector<value_type> tmp(ext);
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
tmp[i] = test_view_dc_h(i);
|
||||||
|
}
|
||||||
|
// run adj-diff on tmp directly
|
||||||
|
std::adjacent_difference(tmp.begin(), tmp.end(), tmp.begin(),
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
// copy from tmp to gold_h
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
gold_view_h(i) = tmp[i];
|
||||||
|
}
|
||||||
|
// deep_copy to device
|
||||||
|
Kokkos::deep_copy(gold_view, gold_view_h);
|
||||||
|
return gold_view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TestViewType, class GoldViewType>
|
||||||
|
void verify_data(TestViewType test_view, GoldViewType gold) {
|
||||||
|
// we need to be careful because test_view might not be deep copyable
|
||||||
|
// for instance strided layout
|
||||||
|
|
||||||
|
auto test_view_dc = create_deep_copyable_compatible_clone(test_view);
|
||||||
|
auto test_view_dc_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), test_view_dc);
|
||||||
|
// gold is deep_copyable for sure
|
||||||
|
const auto gold_h = create_mirror_view_and_copy(Kokkos::HostSpace(), gold);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < test_view.extent(0); ++i) {
|
||||||
|
EXPECT_TRUE(gold_h(i) == test_view_dc_h(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType1, class ValueType2 = ValueType1,
|
||||||
|
class RetType = ValueType2>
|
||||||
|
struct CustomBinaryOpFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
RetType operator()(const ValueType1& a, const ValueType2& b) const {
|
||||||
|
return a * b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType1, class ValueType2 = ValueType1,
|
||||||
|
class RetType = ValueType2>
|
||||||
|
struct DefaultBinaryOpFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
RetType operator()(const ValueType1& a, const ValueType2& b) const {
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class... Args>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info,
|
||||||
|
Args... args /* copy on purpose */) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "adj_diff_from_view");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
const auto gold = compute_gold(view_from, name, args...);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "adj_diff_dest_view");
|
||||||
|
auto res1 = KE::adjacent_difference(exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), args...);
|
||||||
|
EXPECT_TRUE(res1 == KE::end(view_dest));
|
||||||
|
verify_data(view_dest, gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "adj_diff_dest_view");
|
||||||
|
auto res2 = KE::adjacent_difference(
|
||||||
|
"label", exespace(), KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), args...);
|
||||||
|
EXPECT_TRUE(res2 == KE::end(view_dest));
|
||||||
|
verify_data(view_dest, gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "adj_diff_dest_view");
|
||||||
|
auto res3 =
|
||||||
|
KE::adjacent_difference(exespace(), view_from, view_dest, args...);
|
||||||
|
EXPECT_TRUE(res3 == KE::end(view_dest));
|
||||||
|
verify_data(view_dest, gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "adj_diff_dest_view");
|
||||||
|
auto res4 = KE::adjacent_difference("label", exespace(), view_from,
|
||||||
|
view_dest, args...);
|
||||||
|
EXPECT_TRUE(res4 == KE::end(view_dest));
|
||||||
|
verify_data(view_dest, gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class... Args>
|
||||||
|
void run_all_scenarios(Args... args /* copy on purpose */) {
|
||||||
|
// if (0 < sizeof...(args)) {
|
||||||
|
// std::cout << "adjacent_difference: " << view_tag_to_string(Tag{})
|
||||||
|
// << ", custom binary op, all overloads \n";
|
||||||
|
// } else {
|
||||||
|
// std::cout << "adjacent_difference: " << view_tag_to_string(Tag{})
|
||||||
|
// << ", default binary op, all overloads \n";
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (const auto& it : default_scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, args...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_numerics_ops_test, adjecent_difference) {
|
||||||
|
using value_type = double;
|
||||||
|
|
||||||
|
run_all_scenarios<DynamicTag, value_type>();
|
||||||
|
run_all_scenarios<StridedTwoTag, value_type>();
|
||||||
|
run_all_scenarios<StridedThreeTag, value_type>();
|
||||||
|
|
||||||
|
using custom_binary_op = CustomBinaryOpFunctor<value_type>;
|
||||||
|
run_all_scenarios<DynamicTag, value_type>(custom_binary_op{});
|
||||||
|
run_all_scenarios<StridedTwoTag, value_type>(custom_binary_op{});
|
||||||
|
run_all_scenarios<StridedThreeTag, value_type>(custom_binary_op{});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace AdjacentDifference
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,325 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace AdjacentFind {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
// impl is here for std because it is only avail from c++>=17
|
||||||
|
template <class InputIterator, class OutputIterator, class BinaryPredicate>
|
||||||
|
auto my_unique_copy(InputIterator first, InputIterator last,
|
||||||
|
OutputIterator result, BinaryPredicate pred) {
|
||||||
|
if (first != last) {
|
||||||
|
typename OutputIterator::value_type t(*first);
|
||||||
|
*result = t;
|
||||||
|
++result;
|
||||||
|
while (++first != last) {
|
||||||
|
if (!pred(t, *first)) {
|
||||||
|
t = *first;
|
||||||
|
*result = t;
|
||||||
|
++result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class InputIterator, class OutputIterator>
|
||||||
|
auto my_unique_copy(InputIterator first, InputIterator last,
|
||||||
|
OutputIterator result) {
|
||||||
|
using value_type = typename OutputIterator::value_type;
|
||||||
|
using func_t = IsEqualFunctor<value_type>;
|
||||||
|
return my_unique_copy(first, last, result, func_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
// make bounds tight so that it is likely we get
|
||||||
|
// consecutive equal elements
|
||||||
|
UnifDist() : m_dist(2, 8) { m_gen.seed(345823); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
// make bounds tight so that it is likely we get
|
||||||
|
// consecutive equal elements
|
||||||
|
UnifDist() : m_dist(2, 8) { m_gen.seed(345823); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(0);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(2);
|
||||||
|
v_h(3) = static_cast<value_type>(3);
|
||||||
|
v_h(4) = static_cast<value_type>(2);
|
||||||
|
v_h(5) = static_cast<value_type>(5);
|
||||||
|
v_h(6) = static_cast<value_type>(4);
|
||||||
|
v_h(7) = static_cast<value_type>(4);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(6);
|
||||||
|
v_h(10) = static_cast<value_type>(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(3);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(4);
|
||||||
|
v_h(7) = static_cast<value_type>(4);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(6);
|
||||||
|
v_h(10) = static_cast<value_type>(8);
|
||||||
|
v_h(11) = static_cast<value_type>(9);
|
||||||
|
v_h(12) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium") {
|
||||||
|
// beginning just contains increasing values
|
||||||
|
for (std::size_t i = 0; i < 1000; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then use random
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 1000; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-a") {
|
||||||
|
// put equal elements at the end
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
v_h(ext - 3) = static_cast<value_type>(44);
|
||||||
|
v_h(ext - 2) = static_cast<value_type>(44);
|
||||||
|
v_h(ext - 1) = static_cast<value_type>(44);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-b") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class IteratorType, class BinaryPredicate>
|
||||||
|
IteratorType my_std_adjacent_find(IteratorType first, IteratorType last,
|
||||||
|
BinaryPredicate p) {
|
||||||
|
if (first == last) {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
IteratorType next = first;
|
||||||
|
++next;
|
||||||
|
for (; next != last; ++next, ++first) {
|
||||||
|
if (p(*first, *next)) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class IteratorType>
|
||||||
|
IteratorType my_std_adjacent_find(IteratorType first, IteratorType last) {
|
||||||
|
using value_type = typename IteratorType::value_type;
|
||||||
|
return my_std_adjacent_find(first, last, IsEqualFunctor<value_type>());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name) {
|
||||||
|
std::cout << "adjacent_find: default predicate: " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class Predicate>
|
||||||
|
void print_scenario_details(const std::string& name, Predicate pred) {
|
||||||
|
(void)pred;
|
||||||
|
std::cout << "adjacent_find: custom predicate: " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class DiffType, class ViewType, class... Args>
|
||||||
|
void verify(DiffType my_diff, ViewType view, Args... args) {
|
||||||
|
auto view_dc = create_deep_copyable_compatible_clone(view);
|
||||||
|
auto view_h = create_mirror_view_and_copy(Kokkos::HostSpace(), view_dc);
|
||||||
|
auto std_r =
|
||||||
|
my_std_adjacent_find(KE::cbegin(view_h), KE::cend(view_h), args...);
|
||||||
|
const auto std_diff = std_r - KE::cbegin(view_h);
|
||||||
|
|
||||||
|
EXPECT_TRUE(my_diff == std_diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class... Args>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info, Args... args) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, args...);
|
||||||
|
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "adjacent_find_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto res_it = KE::adjacent_find(exespace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), args...);
|
||||||
|
const auto my_diff = res_it - KE::cbegin(view);
|
||||||
|
verify(my_diff, view, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto res_it = KE::adjacent_find("label", exespace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), args...);
|
||||||
|
const auto my_diff = res_it - KE::cbegin(view);
|
||||||
|
verify(my_diff, view, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto res_it = KE::adjacent_find(exespace(), view, args...);
|
||||||
|
const auto my_diff = res_it - KE::begin(view);
|
||||||
|
verify(my_diff, view, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto res_it = KE::adjacent_find("label", exespace(), view, args...);
|
||||||
|
const auto my_diff = res_it - KE::begin(view);
|
||||||
|
verify(my_diff, view, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 11},
|
||||||
|
{"small-b", 13}, {"medium", 21103}, {"large-a", 101513},
|
||||||
|
{"large-b", 100111}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
|
||||||
|
using func_t = IsEqualFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, func_t());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_nonmod_seq_ops, adjacent_find) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace AdjacentFind
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace AllAnyNoneOf {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_all_of(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
using view_host_space_t = Kokkos::View<value_t*, Kokkos::HostSpace>;
|
||||||
|
const auto equals_zero = EqualsValFunctor<value_t>(0);
|
||||||
|
|
||||||
|
view_host_space_t expected("all_of_expected", view.extent(0));
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
// reference result
|
||||||
|
EXPECT_TRUE(std::all_of(KE::begin(expected), KE::end(expected), equals_zero));
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_TRUE(
|
||||||
|
KE::all_of(exespace(), KE::begin(view), KE::end(view), equals_zero));
|
||||||
|
// pass view
|
||||||
|
EXPECT_TRUE(KE::all_of(exespace(), view, equals_zero));
|
||||||
|
|
||||||
|
fill_views_inc(view, expected);
|
||||||
|
|
||||||
|
if (view.extent(0) > 1) {
|
||||||
|
// reference result
|
||||||
|
EXPECT_FALSE(
|
||||||
|
std::all_of(KE::begin(expected), KE::end(expected), equals_zero));
|
||||||
|
|
||||||
|
// pass const iterators
|
||||||
|
EXPECT_FALSE(
|
||||||
|
KE::all_of(exespace(), KE::cbegin(view), KE::cend(view), equals_zero));
|
||||||
|
// pass view
|
||||||
|
EXPECT_FALSE(KE::all_of("label", exespace(), view, equals_zero));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_any_of(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
using view_host_space_t = Kokkos::View<value_t*, Kokkos::HostSpace>;
|
||||||
|
const auto not_equals_zero = NotEqualsZeroFunctor<value_t>();
|
||||||
|
|
||||||
|
view_host_space_t expected("any_of_expected", view.extent(0));
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
// reference result
|
||||||
|
EXPECT_FALSE(
|
||||||
|
std::any_of(KE::begin(expected), KE::end(expected), not_equals_zero));
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_FALSE(
|
||||||
|
KE::any_of(exespace(), KE::begin(view), KE::end(view), not_equals_zero));
|
||||||
|
// pass view
|
||||||
|
EXPECT_FALSE(KE::any_of(exespace(), view, not_equals_zero));
|
||||||
|
|
||||||
|
fill_views_inc(view, expected);
|
||||||
|
|
||||||
|
if (view.extent(0) > 1) {
|
||||||
|
// reference result
|
||||||
|
EXPECT_TRUE(
|
||||||
|
std::any_of(KE::begin(expected), KE::end(expected), not_equals_zero));
|
||||||
|
|
||||||
|
// pass const iterators
|
||||||
|
EXPECT_TRUE(KE::any_of(exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
not_equals_zero));
|
||||||
|
// pass view
|
||||||
|
EXPECT_TRUE(KE::any_of("label", exespace(), view, not_equals_zero));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_none_of(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
using view_host_space_t = Kokkos::View<value_t*, Kokkos::HostSpace>;
|
||||||
|
const auto is_positive = IsPositiveFunctor<value_t>();
|
||||||
|
|
||||||
|
view_host_space_t expected("none_of_expected", view.extent(0));
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
// reference result
|
||||||
|
EXPECT_TRUE(
|
||||||
|
std::none_of(KE::begin(expected), KE::end(expected), is_positive));
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_TRUE(
|
||||||
|
KE::none_of(exespace(), KE::begin(view), KE::end(view), is_positive));
|
||||||
|
// pass view
|
||||||
|
EXPECT_TRUE(KE::none_of(exespace(), view, is_positive));
|
||||||
|
|
||||||
|
fill_views_inc(view, expected);
|
||||||
|
|
||||||
|
if (view.extent(0) > 1) {
|
||||||
|
// reference result
|
||||||
|
EXPECT_FALSE(
|
||||||
|
std::none_of(KE::begin(expected), KE::end(expected), is_positive));
|
||||||
|
|
||||||
|
// pass const iterators
|
||||||
|
EXPECT_FALSE(
|
||||||
|
KE::none_of(exespace(), KE::cbegin(view), KE::cend(view), is_positive));
|
||||||
|
// pass view
|
||||||
|
EXPECT_FALSE(KE::none_of("label", exespace(), view, is_positive));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
for (const auto& scenario : default_scenarios) {
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "all_of");
|
||||||
|
test_all_of(view);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "any_of");
|
||||||
|
test_any_of(view);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "none_of");
|
||||||
|
test_none_of(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_all_any_none_of_test, test) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedTwoTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, unsigned>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace AllAnyNoneOf
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
57
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsCommon.cpp
Normal file
57
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsCommon.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
std::string view_tag_to_string(DynamicTag) { return "dynamic_view"; }
|
||||||
|
|
||||||
|
std::string view_tag_to_string(StridedTwoTag) { return "stride2_view"; }
|
||||||
|
|
||||||
|
std::string view_tag_to_string(StridedThreeTag) { return "stride3_view"; }
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
255
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsCommon.hpp
Normal file
255
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsCommon.hpp
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_ALGORITHMS_UNITTESTS_TEST_STD_ALGOS_COMMON_HPP
|
||||||
|
#define KOKKOS_ALGORITHMS_UNITTESTS_TEST_STD_ALGOS_COMMON_HPP
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <TestStdAlgorithmsHelperFunctors.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <numeric>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
using exespace = Kokkos::DefaultExecutionSpace;
|
||||||
|
|
||||||
|
struct DynamicTag {};
|
||||||
|
struct StridedTwoTag {};
|
||||||
|
struct StridedThreeTag {};
|
||||||
|
|
||||||
|
const std::map<std::string, std::size_t> default_scenarios = {
|
||||||
|
{"empty", 0}, {"one-element", 1}, {"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2}, {"small-a", 9}, {"small-b", 13},
|
||||||
|
{"medium-a", 1003}, {"medium-b", 1003}, {"large-a", 101513},
|
||||||
|
{"large-b", 101513}};
|
||||||
|
|
||||||
|
// see cpp file for these functions
|
||||||
|
std::string view_tag_to_string(DynamicTag);
|
||||||
|
std::string view_tag_to_string(StridedTwoTag);
|
||||||
|
std::string view_tag_to_string(StridedThreeTag);
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
auto create_view(DynamicTag, std::size_t ext, const std::string label) {
|
||||||
|
using view_t = Kokkos::View<ValueType*>;
|
||||||
|
view_t view{label + "_" + view_tag_to_string(DynamicTag{}), ext};
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
auto create_view(StridedTwoTag, std::size_t ext, const std::string label) {
|
||||||
|
using view_t = Kokkos::View<ValueType*, Kokkos::LayoutStride>;
|
||||||
|
Kokkos::LayoutStride layout{ext, 2};
|
||||||
|
view_t view{label + "_" + view_tag_to_string(DynamicTag{}), layout};
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
auto create_view(StridedThreeTag, std::size_t ext, const std::string label) {
|
||||||
|
using view_t = Kokkos::View<ValueType*, Kokkos::LayoutStride>;
|
||||||
|
Kokkos::LayoutStride layout{ext, 3};
|
||||||
|
view_t view{label + "_" + view_tag_to_string(DynamicTag{}), layout};
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
auto create_deep_copyable_compatible_view_with_same_extent(ViewType view) {
|
||||||
|
const std::size_t ext = view.extent(0);
|
||||||
|
using view_value_type = typename ViewType::value_type;
|
||||||
|
using view_exespace = typename ViewType::execution_space;
|
||||||
|
using view_deep_copyable_t = Kokkos::View<view_value_type*, view_exespace>;
|
||||||
|
view_deep_copyable_t view_dc("view_dc", ext);
|
||||||
|
return view_dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
auto create_deep_copyable_compatible_clone(ViewType view) {
|
||||||
|
auto view_dc = create_deep_copyable_compatible_view_with_same_extent(view);
|
||||||
|
using view_dc_t = decltype(view_dc);
|
||||||
|
CopyFunctor<ViewType, view_dc_t> F1(view, view_dc);
|
||||||
|
Kokkos::parallel_for("copy", view.extent(0), F1);
|
||||||
|
return view_dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
auto create_host_space_copy(ViewType view) {
|
||||||
|
auto view_dc = create_deep_copyable_compatible_clone(view);
|
||||||
|
return create_mirror_view_and_copy(Kokkos::HostSpace(), view_dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill the views with sequentially increasing values
|
||||||
|
template <class ViewType, class ViewHostType>
|
||||||
|
void fill_views_inc(ViewType view, ViewHostType host_view) {
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
Kokkos::parallel_for(view.extent(0), AssignIndexFunctor<ViewType>(view));
|
||||||
|
std::iota(KE::begin(host_view), KE::end(host_view), 0);
|
||||||
|
// compare_views(expected, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType, class ViewType>
|
||||||
|
std::enable_if_t<!std::is_same<typename ViewType::traits::array_layout,
|
||||||
|
Kokkos::LayoutStride>::value>
|
||||||
|
verify_values(ValueType expected, const ViewType view) {
|
||||||
|
static_assert(std::is_same<ValueType, typename ViewType::value_type>::value,
|
||||||
|
"Non-matching value types of view and reference value");
|
||||||
|
auto view_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), view);
|
||||||
|
for (std::size_t i = 0; i < view_h.extent(0); i++) {
|
||||||
|
EXPECT_EQ(expected, view_h(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType, class ViewType>
|
||||||
|
std::enable_if_t<std::is_same<typename ViewType::traits::array_layout,
|
||||||
|
Kokkos::LayoutStride>::value>
|
||||||
|
verify_values(ValueType expected, const ViewType view) {
|
||||||
|
static_assert(std::is_same<ValueType, typename ViewType::value_type>::value,
|
||||||
|
"Non-matching value types of view and reference value");
|
||||||
|
|
||||||
|
using non_strided_view_t = Kokkos::View<typename ViewType::value_type*>;
|
||||||
|
non_strided_view_t tmpView("tmpView", view.extent(0));
|
||||||
|
|
||||||
|
Kokkos::parallel_for(
|
||||||
|
"_std_algo_copy", view.extent(0),
|
||||||
|
CopyFunctor<ViewType, non_strided_view_t>(view, tmpView));
|
||||||
|
auto view_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), tmpView);
|
||||||
|
for (std::size_t i = 0; i < view_h.extent(0); i++) {
|
||||||
|
EXPECT_EQ(expected, view_h(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2>
|
||||||
|
std::enable_if_t<!std::is_same<typename ViewType2::traits::array_layout,
|
||||||
|
Kokkos::LayoutStride>::value>
|
||||||
|
compare_views(ViewType1 expected, const ViewType2 actual) {
|
||||||
|
static_assert(std::is_same<typename ViewType1::value_type,
|
||||||
|
typename ViewType2::value_type>::value,
|
||||||
|
"Non-matching value types of expected and actual view");
|
||||||
|
auto expected_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), expected);
|
||||||
|
auto actual_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), actual);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < expected_h.extent(0); i++) {
|
||||||
|
EXPECT_EQ(expected_h(i), actual_h(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2>
|
||||||
|
std::enable_if_t<std::is_same<typename ViewType2::traits::array_layout,
|
||||||
|
Kokkos::LayoutStride>::value>
|
||||||
|
compare_views(ViewType1 expected, const ViewType2 actual) {
|
||||||
|
static_assert(std::is_same<typename ViewType1::value_type,
|
||||||
|
typename ViewType2::value_type>::value,
|
||||||
|
"Non-matching value types of expected and actual view");
|
||||||
|
|
||||||
|
using non_strided_view_t = Kokkos::View<typename ViewType2::value_type*>;
|
||||||
|
non_strided_view_t tmp_view("tmp_view", actual.extent(0));
|
||||||
|
Kokkos::parallel_for(
|
||||||
|
"_std_algo_copy", actual.extent(0),
|
||||||
|
CopyFunctor<ViewType2, non_strided_view_t>(actual, tmp_view));
|
||||||
|
|
||||||
|
auto actual_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), tmp_view);
|
||||||
|
auto expected_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), expected);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < expected_h.extent(0); i++) {
|
||||||
|
EXPECT_EQ(expected_h(i), actual_h(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_zero(ViewType a) {
|
||||||
|
const auto functor = FillZeroFunctor<ViewType>(a);
|
||||||
|
::Kokkos::parallel_for(a.extent(0), std::move(functor));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2>
|
||||||
|
void fill_zero(ViewType1 a, ViewType2 b) {
|
||||||
|
fill_zero(a);
|
||||||
|
fill_zero(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// helpers for testing small views (extent = 10)
|
||||||
|
// prefer `default_scenarios` map for creating new tests
|
||||||
|
using value_type = double;
|
||||||
|
|
||||||
|
struct std_algorithms_test : public ::testing::Test {
|
||||||
|
static constexpr size_t extent = 10;
|
||||||
|
|
||||||
|
using static_view_t = Kokkos::View<value_type[extent]>;
|
||||||
|
static_view_t m_static_view{"std-algo-test-1D-contiguous-view-static"};
|
||||||
|
|
||||||
|
using dyn_view_t = Kokkos::View<value_type*>;
|
||||||
|
dyn_view_t m_dynamic_view{"std-algo-test-1D-contiguous-view-dynamic", extent};
|
||||||
|
|
||||||
|
using strided_view_t = Kokkos::View<value_type*, Kokkos::LayoutStride>;
|
||||||
|
Kokkos::LayoutStride layout{extent, 2};
|
||||||
|
strided_view_t m_strided_view{"std-algo-test-1D-strided-view", layout};
|
||||||
|
|
||||||
|
using view_host_space_t = Kokkos::View<value_type[10], Kokkos::HostSpace>;
|
||||||
|
|
||||||
|
template <class ViewFromType>
|
||||||
|
void copyInputViewToFixtureViews(ViewFromType view) {
|
||||||
|
CopyFunctor<ViewFromType, static_view_t> F1(view, m_static_view);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy1", view.extent(0), F1);
|
||||||
|
|
||||||
|
CopyFunctor<ViewFromType, dyn_view_t> F2(view, m_dynamic_view);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy2", view.extent(0), F2);
|
||||||
|
|
||||||
|
CopyFunctor<ViewFromType, strided_view_t> F3(view, m_strided_view);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy3", view.extent(0), F3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,553 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <Kokkos_StdAlgorithms.hpp>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace compileonly {
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TrivialUnaryFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType a) const { return a; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TrivialBinaryFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType &a, const ValueType &b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const volatile ValueType &a,
|
||||||
|
const volatile ValueType &b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TrivialUnaryPredicate {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType val) const {
|
||||||
|
(void)val;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TrivialBinaryPredicate {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType val, const ValueType val2) const {
|
||||||
|
(void)val;
|
||||||
|
(void)val2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TimesTwoFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(ValueType &val) const { val *= (ValueType)2; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TrivialComparator {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType &a, const ValueType &b) const {
|
||||||
|
return a > b;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const volatile ValueType &a,
|
||||||
|
const volatile ValueType &b) const {
|
||||||
|
return a > b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TrivialGenerator {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()() const { return ValueType{}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TrivialReduceJoinFunctor {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
ValueType operator()(const ValueType &a, const ValueType &b) const {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
ValueType operator()(const volatile ValueType &a,
|
||||||
|
const volatile ValueType &b) const {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TrivialTransformReduceUnaryTransformer {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
ValueType operator()(const ValueType &a) const { return a; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TrivialTransformReduceBinaryTransformer {
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
ValueType operator()(const ValueType &a, const ValueType &b) const {
|
||||||
|
return (a * b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// put all code here and don't call from main
|
||||||
|
// so that even if one runs the executable,
|
||||||
|
// nothing is run anyway
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
using count_type = std::size_t;
|
||||||
|
using T = double;
|
||||||
|
Kokkos::View<T *> in1("in1", 10);
|
||||||
|
Kokkos::View<T *> in2("in2", 10);
|
||||||
|
Kokkos::View<T *> in3("in3", 10);
|
||||||
|
Kokkos::DefaultExecutionSpace exe_space;
|
||||||
|
std::string const label = "trivial";
|
||||||
|
|
||||||
|
//
|
||||||
|
// just iterators
|
||||||
|
//
|
||||||
|
#define TEST_ALGO_MACRO_B1E1(ALGO) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1)); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1));
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1E1B2(ALGO) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2)); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2));
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1E1B2E2(ALGO) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2), KE::end(in2)); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2), KE::end(in2));
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1E1E2(ALGO) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::end(in2)); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1), KE::end(in2));
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1E1E2B3(ALGO) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1), KE::end(in2), \
|
||||||
|
KE::begin(in3)); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1), KE::end(in2), \
|
||||||
|
KE::begin(in3));
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1E1E1B2(ALGO) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2)); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2));
|
||||||
|
|
||||||
|
//
|
||||||
|
// iterators and params
|
||||||
|
//
|
||||||
|
#define TEST_ALGO_MACRO_B1_VARIAD(ALGO, ...) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), __VA_ARGS__); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), __VA_ARGS__);
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1E1_VARIAD(ALGO, ...) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1), __VA_ARGS__); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1), __VA_ARGS__);
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1E1B2_VARIAD(ALGO, ...) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2), __VA_ARGS__); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2), __VA_ARGS__);
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1_ARG_B2(ALGO, ARG) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), ARG, KE::begin(in2)); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), ARG, KE::begin(in2));
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1E1B2B3_VARIAD(ALGO, ...) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2), KE::begin(in3), __VA_ARGS__); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2), KE::begin(in3), __VA_ARGS__);
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_B1E1B2E2_VARIAD(ALGO, ARG) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2), KE::end(in2), ARG); \
|
||||||
|
(void)KE::ALGO(label, exe_space, KE::begin(in1), KE::end(in1), \
|
||||||
|
KE::begin(in2), KE::end(in2), ARG);
|
||||||
|
|
||||||
|
//
|
||||||
|
// views only
|
||||||
|
//
|
||||||
|
#define TEST_ALGO_MACRO_V1(ALGO) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ in1); \
|
||||||
|
(void)KE::ALGO(label, exe_space, in1);
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_V1V2(ALGO) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ in1, in2); \
|
||||||
|
(void)KE::ALGO(label, exe_space, in1, in2);
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_V1V2V3(ALGO) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ in1, in2, in3); \
|
||||||
|
(void)KE::ALGO(label, exe_space, in1, in2, in3);
|
||||||
|
|
||||||
|
//
|
||||||
|
// views and params
|
||||||
|
//
|
||||||
|
#define TEST_ALGO_MACRO_V1_VARIAD(ALGO, ...) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ in1, __VA_ARGS__); \
|
||||||
|
(void)KE::ALGO(label, exe_space, in1, __VA_ARGS__);
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_V1V2_VARIAD(ALGO, ...) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ in1, in2, __VA_ARGS__); \
|
||||||
|
(void)KE::ALGO(label, exe_space, in1, in2, __VA_ARGS__);
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_V1V2V3_VARIAD(ALGO, ...) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ in1, in2, in3, __VA_ARGS__); \
|
||||||
|
(void)KE::ALGO(label, exe_space, in1, in2, in3, __VA_ARGS__);
|
||||||
|
|
||||||
|
#define TEST_ALGO_MACRO_V1_ARG_V2(ALGO, ARG) \
|
||||||
|
(void)KE::ALGO(exe_space, /*--*/ in1, ARG, in2); \
|
||||||
|
(void)KE::ALGO(label, exe_space, in1, ARG, in2);
|
||||||
|
|
||||||
|
void non_modifying_seq_ops() {
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(find, T{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(find, T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(find_if, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(find_if, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(find_if_not, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(find_if_not, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(for_each, TimesTwoFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(for_each, TimesTwoFunctor<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1_VARIAD(for_each_n, count_type{}, TimesTwoFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(for_each_n, count_type{}, TimesTwoFunctor<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(count_if, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(count_if, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(count, T{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(count, T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2(mismatch);
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2_VARIAD(mismatch, TrivialBinaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2(mismatch);
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(mismatch, TrivialBinaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(all_of, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(all_of, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(any_of, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(any_of, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(none_of, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(none_of, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2(equal);
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(equal, TrivialBinaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2(equal);
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(equal, TrivialBinaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2(equal);
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2_VARIAD(equal, TrivialBinaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2(lexicographical_compare);
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2_VARIAD(lexicographical_compare,
|
||||||
|
TrivialComparator<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2(lexicographical_compare);
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(lexicographical_compare, TrivialComparator<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1(adjacent_find);
|
||||||
|
TEST_ALGO_MACRO_V1(adjacent_find);
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(adjacent_find, TrivialBinaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(adjacent_find, TrivialBinaryFunctor<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2(search);
|
||||||
|
TEST_ALGO_MACRO_V1V2(search);
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2_VARIAD(search, TrivialBinaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(search, TrivialBinaryFunctor<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2(find_first_of);
|
||||||
|
TEST_ALGO_MACRO_V1V2(find_first_of);
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2_VARIAD(find_first_of, TrivialBinaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(find_first_of, TrivialBinaryFunctor<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(search_n, count_type{}, T{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(search_n, count_type{}, T{});
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(search_n, count_type{}, T{},
|
||||||
|
TrivialBinaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(search_n, count_type{}, T{},
|
||||||
|
TrivialBinaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2(find_end);
|
||||||
|
TEST_ALGO_MACRO_V1V2(find_end);
|
||||||
|
TEST_ALGO_MACRO_B1E1B2E2_VARIAD(find_end, TrivialBinaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(find_end, TrivialBinaryFunctor<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void modifying_seq_ops() {
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(replace_copy, T{}, T{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(replace_copy, T{}, T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(replace_copy_if, TrivialUnaryPredicate<T>(),
|
||||||
|
T{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(replace_copy_if, TrivialUnaryPredicate<T>(), T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(replace, T{}, T{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(replace, T{}, T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(replace_if, TrivialUnaryPredicate<T>(), T{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(replace_if, TrivialUnaryPredicate<T>(), T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2(copy);
|
||||||
|
TEST_ALGO_MACRO_V1V2(copy);
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1_ARG_B2(copy_n, count_type{});
|
||||||
|
TEST_ALGO_MACRO_V1_ARG_V2(copy_n, count_type{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2(copy_backward);
|
||||||
|
TEST_ALGO_MACRO_V1V2(copy_backward);
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(copy_if, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(copy_if, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(fill, T{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(fill, T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1_VARIAD(fill_n, count_type{}, T{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(fill_n, count_type{}, T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(transform, TrivialUnaryFunctor<T>{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(transform, TrivialUnaryFunctor<T>{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(transform, TrivialUnaryFunctor<T>{});
|
||||||
|
TEST_ALGO_MACRO_B1E1B2B3_VARIAD(transform, TrivialBinaryFunctor<T>{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(transform, TrivialUnaryFunctor<T>{});
|
||||||
|
TEST_ALGO_MACRO_V1V2V3_VARIAD(transform, TrivialBinaryFunctor<T>{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(generate, TrivialGenerator<T>{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(generate, TrivialGenerator<T>{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1_VARIAD(generate_n, count_type{}, TrivialGenerator<T>{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(generate_n, count_type{}, TrivialGenerator<T>{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2(reverse_copy);
|
||||||
|
TEST_ALGO_MACRO_V1V2(reverse_copy);
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1(reverse);
|
||||||
|
TEST_ALGO_MACRO_V1(reverse);
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2(move);
|
||||||
|
TEST_ALGO_MACRO_V1V2(move);
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1E2(move_backward);
|
||||||
|
TEST_ALGO_MACRO_V1V2(move_backward);
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2(swap_ranges);
|
||||||
|
TEST_ALGO_MACRO_V1V2(swap_ranges);
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1(unique);
|
||||||
|
TEST_ALGO_MACRO_V1(unique);
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(unique, TrivialBinaryPredicate<T>{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(unique, TrivialBinaryPredicate<T>{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2(unique_copy);
|
||||||
|
TEST_ALGO_MACRO_V1V2(unique_copy);
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(unique_copy, TrivialBinaryPredicate<T>{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(unique_copy, TrivialBinaryPredicate<T>{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1E2(rotate);
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(rotate, count_type{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1E1B2(rotate_copy);
|
||||||
|
TEST_ALGO_MACRO_V1_ARG_V2(rotate_copy, count_type{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(remove_if, TrivialUnaryPredicate<T>{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(remove_if, TrivialUnaryPredicate<T>{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(remove, T{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(remove, T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(remove_copy, T{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(remove_copy, T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(remove_copy_if, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(remove_copy_if, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(shift_left, count_type{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(shift_left, count_type{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(shift_right, count_type{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(shift_right, count_type{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void sorting_ops() {
|
||||||
|
TEST_ALGO_MACRO_B1E1(is_sorted_until);
|
||||||
|
TEST_ALGO_MACRO_V1(is_sorted_until);
|
||||||
|
|
||||||
|
#ifndef KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(is_sorted_until, TrivialComparator<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(is_sorted_until, TrivialComparator<T>());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1(is_sorted);
|
||||||
|
TEST_ALGO_MACRO_V1(is_sorted);
|
||||||
|
|
||||||
|
#ifndef KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(is_sorted, TrivialComparator<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(is_sorted, TrivialComparator<T>());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void minmax_ops() {
|
||||||
|
TEST_ALGO_MACRO_B1E1(min_element);
|
||||||
|
TEST_ALGO_MACRO_V1(min_element);
|
||||||
|
TEST_ALGO_MACRO_B1E1(max_element);
|
||||||
|
TEST_ALGO_MACRO_V1(max_element);
|
||||||
|
TEST_ALGO_MACRO_B1E1(minmax_element);
|
||||||
|
TEST_ALGO_MACRO_V1(minmax_element);
|
||||||
|
|
||||||
|
#ifndef KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(min_element, TrivialComparator<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(min_element, TrivialComparator<T>());
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(max_element, TrivialComparator<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(max_element, TrivialComparator<T>());
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(minmax_element, TrivialComparator<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(minmax_element, TrivialComparator<T>());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void partitionig_ops() {
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(is_partitioned, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(is_partitioned, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2B3_VARIAD(partition_copy, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2V3_VARIAD(partition_copy, TrivialUnaryPredicate<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(partition_point, TrivialUnaryPredicate<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(partition_point, TrivialUnaryPredicate<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void numeric() {
|
||||||
|
TEST_ALGO_MACRO_B1E1B2(adjacent_difference);
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(adjacent_difference, TrivialBinaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2(adjacent_difference);
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(adjacent_difference, TrivialBinaryFunctor<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(exclusive_scan, T{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(exclusive_scan, T{});
|
||||||
|
#ifndef KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(exclusive_scan, T{}, TrivialBinaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(exclusive_scan, T{}, TrivialBinaryFunctor<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(transform_exclusive_scan, T{},
|
||||||
|
TrivialBinaryFunctor<T>(),
|
||||||
|
TrivialUnaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(transform_exclusive_scan, T{},
|
||||||
|
TrivialBinaryFunctor<T>(),
|
||||||
|
TrivialUnaryFunctor<T>());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2(inclusive_scan);
|
||||||
|
TEST_ALGO_MACRO_V1V2(inclusive_scan);
|
||||||
|
#ifndef KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(inclusive_scan, TrivialBinaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(inclusive_scan, TrivialBinaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(inclusive_scan, TrivialBinaryFunctor<T>(), T{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(inclusive_scan, TrivialBinaryFunctor<T>(), T{});
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(transform_inclusive_scan,
|
||||||
|
TrivialBinaryFunctor<T>(),
|
||||||
|
TrivialUnaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(transform_inclusive_scan,
|
||||||
|
TrivialBinaryFunctor<T>(),
|
||||||
|
TrivialUnaryFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(transform_inclusive_scan,
|
||||||
|
TrivialBinaryFunctor<T>(),
|
||||||
|
TrivialUnaryFunctor<T>(), T{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(transform_inclusive_scan,
|
||||||
|
TrivialBinaryFunctor<T>(),
|
||||||
|
TrivialUnaryFunctor<T>(), T{});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
TEST_ALGO_MACRO_B1E1(reduce);
|
||||||
|
TEST_ALGO_MACRO_V1(reduce);
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(reduce, T{});
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(reduce, T{});
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(reduce, T{}, TrivialReduceJoinFunctor<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(reduce, T{}, TrivialReduceJoinFunctor<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(transform_reduce, T{});
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(transform_reduce, T{});
|
||||||
|
TEST_ALGO_MACRO_B1E1B2_VARIAD(transform_reduce, T{},
|
||||||
|
TrivialReduceJoinFunctor<T>(),
|
||||||
|
TrivialTransformReduceBinaryTransformer<T>());
|
||||||
|
TEST_ALGO_MACRO_V1V2_VARIAD(transform_reduce, T{},
|
||||||
|
TrivialReduceJoinFunctor<T>(),
|
||||||
|
TrivialTransformReduceBinaryTransformer<T>());
|
||||||
|
|
||||||
|
TEST_ALGO_MACRO_B1E1_VARIAD(transform_reduce, T{},
|
||||||
|
TrivialReduceJoinFunctor<T>(),
|
||||||
|
TrivialTransformReduceUnaryTransformer<T>());
|
||||||
|
TEST_ALGO_MACRO_V1_VARIAD(transform_reduce, T{},
|
||||||
|
TrivialReduceJoinFunctor<T>(),
|
||||||
|
TrivialTransformReduceUnaryTransformer<T>());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace compileonly
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
|
|
||||||
|
int main() { return 0; }
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_Constraints.hpp>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
TEST(std_algorithms, is_admissible_to_std_algorithms) {
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
using value_type = double;
|
||||||
|
|
||||||
|
static constexpr size_t extent0 = 13;
|
||||||
|
static constexpr size_t extent1 = 18;
|
||||||
|
static constexpr size_t extent2 = 18;
|
||||||
|
|
||||||
|
//-------------
|
||||||
|
// 1d views
|
||||||
|
//-------------
|
||||||
|
using static_view_1d_t = Kokkos::View<value_type[extent0]>;
|
||||||
|
static_view_1d_t static_view_1d{"std-algo-test-1d-contiguous-view-static"};
|
||||||
|
|
||||||
|
using dyn_view_1d_t = Kokkos::View<value_type*>;
|
||||||
|
dyn_view_1d_t dynamic_view_1d{"std-algo-test-1d-contiguous-view-dynamic",
|
||||||
|
extent0};
|
||||||
|
|
||||||
|
using strided_view_1d_t = Kokkos::View<value_type*, Kokkos::LayoutStride>;
|
||||||
|
Kokkos::LayoutStride layout1d{extent0, 2};
|
||||||
|
strided_view_1d_t strided_view_1d{"std-algo-test-1d-strided-view", layout1d};
|
||||||
|
EXPECT_EQ(layout1d.dimension[0], 13u);
|
||||||
|
EXPECT_EQ(layout1d.stride[0], 2u);
|
||||||
|
// they are admissible
|
||||||
|
KE::Impl::static_assert_is_admissible_to_kokkos_std_algorithms(
|
||||||
|
static_view_1d);
|
||||||
|
KE::Impl::static_assert_is_admissible_to_kokkos_std_algorithms(
|
||||||
|
dynamic_view_1d);
|
||||||
|
KE::Impl::static_assert_is_admissible_to_kokkos_std_algorithms(
|
||||||
|
strided_view_1d);
|
||||||
|
|
||||||
|
//-------------
|
||||||
|
// 2d views
|
||||||
|
//-------------
|
||||||
|
using static_view_2d_t = Kokkos::View<value_type[extent0][extent1]>;
|
||||||
|
using dyn_view_2d_t = Kokkos::View<value_type**>;
|
||||||
|
using strided_view_2d_t = Kokkos::View<value_type**, Kokkos::LayoutStride>;
|
||||||
|
// non admissible
|
||||||
|
EXPECT_FALSE(KE::Impl::is_admissible_to_kokkos_std_algorithms<
|
||||||
|
static_view_2d_t>::value);
|
||||||
|
EXPECT_FALSE(
|
||||||
|
KE::Impl::is_admissible_to_kokkos_std_algorithms<dyn_view_2d_t>::value);
|
||||||
|
EXPECT_FALSE(KE::Impl::is_admissible_to_kokkos_std_algorithms<
|
||||||
|
strided_view_2d_t>::value);
|
||||||
|
|
||||||
|
//-------------
|
||||||
|
// 3d views
|
||||||
|
//-------------
|
||||||
|
using static_view_3d_t = Kokkos::View<value_type[extent0][extent1][extent2]>;
|
||||||
|
using dyn_view_3d_t = Kokkos::View<value_type***>;
|
||||||
|
using strided_view_3d_t = Kokkos::View<value_type***, Kokkos::LayoutStride>;
|
||||||
|
// non admissible
|
||||||
|
EXPECT_FALSE(KE::Impl::is_admissible_to_kokkos_std_algorithms<
|
||||||
|
static_view_3d_t>::value);
|
||||||
|
EXPECT_FALSE(
|
||||||
|
KE::Impl::is_admissible_to_kokkos_std_algorithms<dyn_view_3d_t>::value);
|
||||||
|
EXPECT_FALSE(KE::Impl::is_admissible_to_kokkos_std_algorithms<
|
||||||
|
strided_view_3d_t>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
308
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsCopyIf.cpp
Normal file
308
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsCopyIf.cpp
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace CopyIf {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-100, 100) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType, class PredicateType>
|
||||||
|
std::size_t fill_view(ViewType dest_view, const std::string& name,
|
||||||
|
PredicateType pred) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
std::size_t count = 0;
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
// 1 is not even, so count is not incremented
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = value_type{-5} + static_cast<value_type>(i + 1);
|
||||||
|
if (pred(v_h(i))) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(22);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(-12);
|
||||||
|
}
|
||||||
|
if (pred(v_h(i))) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
if (pred(v_h(i))) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeFrom, class ViewTypeTest, class PredType>
|
||||||
|
void verify_data(const std::string& name, ViewTypeFrom view_from,
|
||||||
|
ViewTypeTest view_test, PredType pred) {
|
||||||
|
using value_type = typename ViewTypeTest::value_type;
|
||||||
|
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
auto view_test_dc = create_deep_copyable_compatible_clone(view_test);
|
||||||
|
auto view_test_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_test_dc);
|
||||||
|
|
||||||
|
auto view_from_dc = create_deep_copyable_compatible_clone(view_from);
|
||||||
|
auto view_from_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_from_dc);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(2));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == static_cast<value_type>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(2));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == static_cast<value_type>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(-4));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == static_cast<value_type>(-2));
|
||||||
|
EXPECT_TRUE(view_test_h(2) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(3) == static_cast<value_type>(2));
|
||||||
|
EXPECT_TRUE(view_test_h(4) == static_cast<value_type>(4));
|
||||||
|
EXPECT_TRUE(view_test_h(5) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(6) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(7) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(8) == static_cast<value_type>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(22));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == static_cast<value_type>(-12));
|
||||||
|
EXPECT_TRUE(view_test_h(2) == static_cast<value_type>(22));
|
||||||
|
EXPECT_TRUE(view_test_h(3) == static_cast<value_type>(-12));
|
||||||
|
EXPECT_TRUE(view_test_h(4) == static_cast<value_type>(22));
|
||||||
|
EXPECT_TRUE(view_test_h(5) == static_cast<value_type>(-12));
|
||||||
|
EXPECT_TRUE(view_test_h(6) == static_cast<value_type>(22));
|
||||||
|
EXPECT_TRUE(view_test_h(7) == static_cast<value_type>(-12));
|
||||||
|
EXPECT_TRUE(view_test_h(8) == static_cast<value_type>(22));
|
||||||
|
EXPECT_TRUE(view_test_h(9) == static_cast<value_type>(-12));
|
||||||
|
EXPECT_TRUE(view_test_h(10) == static_cast<value_type>(22));
|
||||||
|
EXPECT_TRUE(view_test_h(11) == static_cast<value_type>(-12));
|
||||||
|
EXPECT_TRUE(view_test_h(12) == static_cast<value_type>(22));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
// for (std::size_t i = 0; i < view_from_h.extent(0); ++i){
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << " vf = " << view_from_h(i) << " "
|
||||||
|
// << " vt = " << view_test_h(i) << '\n';
|
||||||
|
// }
|
||||||
|
|
||||||
|
std::size_t count = 0;
|
||||||
|
for (std::size_t i = 0; i < view_from_h.extent(0); ++i) {
|
||||||
|
if (pred(view_from_h(i))) {
|
||||||
|
EXPECT_TRUE(view_test_h(count++) == view_from_h(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// all other entries of test view should be zero
|
||||||
|
for (; count < view_test_h.extent(0); ++count) {
|
||||||
|
// std::cout << count << '\n';
|
||||||
|
EXPECT_TRUE(view_test_h(count) == value_type(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "copy_if: " << name << ", " << view_tag_to_string(Tag{}) << ",
|
||||||
|
// "
|
||||||
|
// << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
auto view_from = create_view<ValueType>(Tag{}, view_ext, "copy_if_from");
|
||||||
|
IsEvenFunctor<ValueType> pred;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto n = fill_view(view_from, name, pred);
|
||||||
|
auto view_dest = create_view<ValueType>(Tag{}, view_ext, "copy_if_dest");
|
||||||
|
auto rit = KE::copy_if(exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest), pred);
|
||||||
|
verify_data(name, view_from, view_dest, pred);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + n));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto n = fill_view(view_from, name, pred);
|
||||||
|
auto view_dest = create_view<ValueType>(Tag{}, view_ext, "copy_if_dest");
|
||||||
|
auto rit = KE::copy_if("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest), pred);
|
||||||
|
verify_data(name, view_from, view_dest, pred);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + n));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto n = fill_view(view_from, name, pred);
|
||||||
|
auto view_dest = create_view<ValueType>(Tag{}, view_ext, "copy_if_dest");
|
||||||
|
auto rit = KE::copy_if(exespace(), view_from, view_dest, pred);
|
||||||
|
verify_data(name, view_from, view_dest, pred);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + n));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto n = fill_view(view_from, name, pred);
|
||||||
|
auto view_dest = create_view<ValueType>(Tag{}, view_ext, "copy_if_dest");
|
||||||
|
auto rit = KE::copy_if("label", exespace(), view_from, view_dest, pred);
|
||||||
|
verify_data(name, view_from, view_dest, pred);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + n));
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 1103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, copy_if) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CopyIf
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
142
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsCount.cpp
Normal file
142
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsCount.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Count {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_count(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
using view_host_space_t = Kokkos::View<value_t*, Kokkos::HostSpace>;
|
||||||
|
|
||||||
|
view_host_space_t expected("count_expected", view.extent(0));
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
{
|
||||||
|
const value_t count_value = 0;
|
||||||
|
const auto std_result =
|
||||||
|
std::count(KE::cbegin(expected), KE::cend(expected), count_value);
|
||||||
|
EXPECT_EQ(view.extent(0), size_t(std_result));
|
||||||
|
|
||||||
|
// pass const iterators
|
||||||
|
EXPECT_EQ(std_result, KE::count(exespace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), count_value));
|
||||||
|
// pass view
|
||||||
|
EXPECT_EQ(std_result, KE::count(exespace(), view, count_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const value_t count_value = 13;
|
||||||
|
const auto std_result =
|
||||||
|
std::count(KE::cbegin(expected), KE::cend(expected), count_value);
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_EQ(std_result, KE::count("label", exespace(), KE::begin(view),
|
||||||
|
KE::end(view), count_value));
|
||||||
|
// pass view
|
||||||
|
EXPECT_EQ(std_result, KE::count("label", exespace(), view, count_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_count_if(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
using view_host_space_t = Kokkos::View<value_t*, Kokkos::HostSpace>;
|
||||||
|
|
||||||
|
view_host_space_t expected("count_expected", view.extent(0));
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
// no positive elements (all zeroes)
|
||||||
|
const auto predicate = IsPositiveFunctor<value_type>();
|
||||||
|
EXPECT_EQ(0,
|
||||||
|
std::count_if(KE::begin(expected), KE::end(expected), predicate));
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_EQ(
|
||||||
|
0, KE::count_if(exespace(), KE::begin(view), KE::end(view), predicate));
|
||||||
|
// pass view
|
||||||
|
EXPECT_EQ(0, KE::count_if(exespace(), view, predicate));
|
||||||
|
|
||||||
|
fill_views_inc(view, expected);
|
||||||
|
|
||||||
|
const auto std_result =
|
||||||
|
std::count_if(KE::begin(expected), KE::end(expected), predicate);
|
||||||
|
// pass const iterators
|
||||||
|
EXPECT_EQ(std_result, KE::count_if("label", exespace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), predicate));
|
||||||
|
// pass view
|
||||||
|
EXPECT_EQ(std_result, KE::count_if("label", exespace(), view, predicate));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
for (const auto& scenario : default_scenarios) {
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "count");
|
||||||
|
test_count(view);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "count");
|
||||||
|
test_count_if(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_count_test, test) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedTwoTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, unsigned>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Count
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
150
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsEqual.cpp
Normal file
150
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsEqual.cpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Equal {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_equal(const ViewType view) {
|
||||||
|
auto copy = create_deep_copyable_compatible_clone(view);
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_TRUE(
|
||||||
|
KE::equal(exespace(), KE::begin(view), KE::end(view), KE::begin(copy)));
|
||||||
|
// pass views
|
||||||
|
EXPECT_TRUE(KE::equal(exespace(), view, copy));
|
||||||
|
|
||||||
|
// modify copy - make the last element different
|
||||||
|
const auto extent = view.extent(0);
|
||||||
|
if (extent > 0) {
|
||||||
|
KE::fill(exespace(), KE::end(copy) - 1, KE::end(copy), 1);
|
||||||
|
|
||||||
|
// pass const iterators
|
||||||
|
EXPECT_FALSE(KE::equal(exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::cbegin(copy)));
|
||||||
|
// pass views
|
||||||
|
EXPECT_FALSE(KE::equal("label", exespace(), view, copy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_equal_custom_comparator(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
const auto p = CustomEqualityComparator<value_t>();
|
||||||
|
auto copy = create_deep_copyable_compatible_clone(view);
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_TRUE(KE::equal(exespace(), KE::begin(view), KE::end(view),
|
||||||
|
KE::begin(copy), p));
|
||||||
|
// pass views
|
||||||
|
EXPECT_TRUE(KE::equal(exespace(), view, copy, p));
|
||||||
|
|
||||||
|
// modify copy - make the last element different
|
||||||
|
const auto extent = view.extent(0);
|
||||||
|
if (extent > 0) {
|
||||||
|
KE::fill(exespace(), KE::end(copy) - 1, KE::end(copy), 1);
|
||||||
|
|
||||||
|
// pass const iterators
|
||||||
|
EXPECT_FALSE(KE::equal("label", exespace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), KE::cbegin(copy), p));
|
||||||
|
// pass views
|
||||||
|
EXPECT_FALSE(KE::equal(exespace(), view, copy, p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_equal_4_iterators(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
const auto p = CustomEqualityComparator<value_t>();
|
||||||
|
auto copy = create_deep_copyable_compatible_clone(view);
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_TRUE(KE::equal(exespace(), KE::begin(view), KE::end(view),
|
||||||
|
KE::begin(copy), KE::end(copy)));
|
||||||
|
// pass const and non-const iterators, custom comparator
|
||||||
|
EXPECT_TRUE(KE::equal("label", exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::begin(copy), KE::end(copy), p));
|
||||||
|
|
||||||
|
const auto extent = view.extent(0);
|
||||||
|
if (extent > 0) {
|
||||||
|
// use different length ranges, pass const iterators
|
||||||
|
EXPECT_FALSE(KE::equal(exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::cbegin(copy), KE::cend(copy) - 1));
|
||||||
|
|
||||||
|
// modify copy - make the last element different
|
||||||
|
KE::fill(exespace(), KE::end(copy) - 1, KE::end(copy), 1);
|
||||||
|
// pass const iterators
|
||||||
|
EXPECT_FALSE(KE::equal(exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::cbegin(copy), KE::cend(copy)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
for (const auto& scenario : default_scenarios) {
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "equal");
|
||||||
|
test_equal(view);
|
||||||
|
test_equal_custom_comparator(view);
|
||||||
|
test_equal_4_iterators(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_equal_test, test) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedTwoTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, unsigned>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Equal
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,381 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_Numeric.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace EScan {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(0.05, 1.2) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(1, 3) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_zero(ViewType view) {
|
||||||
|
Kokkos::parallel_for(view.extent(0), FillZeroFunctor<ViewType>(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
v_h(5) = static_cast<value_type>(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// I had to write my own because std::exclusive_scan is ONLY found with
|
||||||
|
// std=c++17
|
||||||
|
template <class it1, class it2, class ValType, class BopType>
|
||||||
|
void my_host_exclusive_scan(it1 first, it1 last, it2 dest, ValType init,
|
||||||
|
BopType bop) {
|
||||||
|
const auto num_elements = last - first;
|
||||||
|
if (num_elements > 0) {
|
||||||
|
while (first < last - 1) {
|
||||||
|
*(dest++) = init;
|
||||||
|
init = bop(*first++, init);
|
||||||
|
}
|
||||||
|
*dest = init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2, class ValueType, class BinaryOp>
|
||||||
|
void verify_data(ViewType1 data_view, // contains data
|
||||||
|
ViewType2 test_view, // the view to test
|
||||||
|
ValueType init_value, BinaryOp bop) {
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
|
||||||
|
auto data_view_dc = create_deep_copyable_compatible_clone(data_view);
|
||||||
|
auto data_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), data_view_dc);
|
||||||
|
|
||||||
|
using gold_view_value_type = typename ViewType2::value_type;
|
||||||
|
Kokkos::View<gold_view_value_type*, Kokkos::HostSpace> gold_h(
|
||||||
|
"goldh", data_view.extent(0));
|
||||||
|
my_host_exclusive_scan(KE::cbegin(data_view_h), KE::cend(data_view_h),
|
||||||
|
KE::begin(gold_h), init_value, bop);
|
||||||
|
|
||||||
|
auto test_view_dc = create_deep_copyable_compatible_clone(test_view);
|
||||||
|
auto test_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), test_view_dc);
|
||||||
|
if (test_view_h.extent(0) > 0) {
|
||||||
|
for (std::size_t i = 0; i < test_view_h.extent(0); ++i) {
|
||||||
|
// std::cout << i << " " << std::setprecision(15) << data_view_h(i) << " "
|
||||||
|
// << gold_h(i) << " " << test_view_h(i) << " "
|
||||||
|
// << std::abs(gold_h(i) - test_view_h(i)) << std::endl;
|
||||||
|
if (std::is_same<gold_view_value_type, int>::value) {
|
||||||
|
EXPECT_TRUE(gold_h(i) == test_view_h(i));
|
||||||
|
} else {
|
||||||
|
const auto error = std::abs(gold_h(i) - test_view_h(i));
|
||||||
|
if (error > 1e-10) {
|
||||||
|
std::cout << i << " " << std::setprecision(15) << data_view_h(i)
|
||||||
|
<< " " << gold_h(i) << " " << test_view_h(i) << " "
|
||||||
|
<< std::abs(gold_h(i) - test_view_h(i)) << std::endl;
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(error < 1e-10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct MultiplyFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return (a * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const volatile ValueType& a,
|
||||||
|
const volatile ValueType& b) const {
|
||||||
|
return (a * b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct SumFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const volatile ValueType& a,
|
||||||
|
const volatile ValueType& b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario_default_op(const InfoType& scenario_info,
|
||||||
|
ValueType init_value) {
|
||||||
|
using default_op = SumFunctor<ValueType>;
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "exclusive_scan default op: " << name << ", "
|
||||||
|
// << view_tag_to_string(Tag{}) << ", "
|
||||||
|
// << value_type_to_string(ValueType()) << ", "
|
||||||
|
// << "init = " << init_value << std::endl;
|
||||||
|
|
||||||
|
auto view_dest = create_view<ValueType>(Tag{}, view_ext, "exclusive_scan");
|
||||||
|
auto view_from = create_view<ValueType>(Tag{}, view_ext, "exclusive_scan");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::exclusive_scan(exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
init_value);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, default_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::exclusive_scan("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
init_value);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, default_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::exclusive_scan(exespace(), view_from, view_dest, init_value);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, default_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::exclusive_scan("label", exespace(), view_from, view_dest,
|
||||||
|
init_value);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, default_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class BinaryOp>
|
||||||
|
void run_single_scenario_custom_op(const InfoType& scenario_info,
|
||||||
|
ValueType init_value, BinaryOp bop) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "exclusive_scan custom op: " << name << ", "
|
||||||
|
// << view_tag_to_string(Tag{}) << ", "
|
||||||
|
// << value_type_to_string(ValueType()) << ", "
|
||||||
|
// << "init = " << init_value << std::endl;
|
||||||
|
|
||||||
|
auto view_dest = create_view<ValueType>(Tag{}, view_ext, "exclusive_scan");
|
||||||
|
auto view_from = create_view<ValueType>(Tag{}, view_ext, "exclusive_scan");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::exclusive_scan(exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
init_value, bop);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, bop);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::exclusive_scan("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
init_value, bop);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, bop);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r =
|
||||||
|
KE::exclusive_scan(exespace(), view_from, view_dest, init_value, bop);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, bop);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::exclusive_scan("label", exespace(), view_from, view_dest,
|
||||||
|
init_value, bop);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, bop);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_exclusive_scan_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element", 1}, {"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2}, {"small-a", 9}, {"small-b", 13},
|
||||||
|
{"medium", 1103}, {"large", 10513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario_default_op<Tag, ValueType>(it, ValueType{0});
|
||||||
|
run_single_scenario_default_op<Tag, ValueType>(it, ValueType{1});
|
||||||
|
run_single_scenario_default_op<Tag, ValueType>(it, ValueType{-2});
|
||||||
|
run_single_scenario_default_op<Tag, ValueType>(it, ValueType{3});
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
// custom multiply op is only run for small views otherwise it overflows
|
||||||
|
if (it.first == "small-a" || it.first == "small-b") {
|
||||||
|
using custom_bop_t = MultiplyFunctor<ValueType>;
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, ValueType{0},
|
||||||
|
custom_bop_t());
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, ValueType{1},
|
||||||
|
custom_bop_t());
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, ValueType{-2},
|
||||||
|
custom_bop_t());
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, ValueType{3},
|
||||||
|
custom_bop_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
using custom_bop_t = SumFunctor<ValueType>;
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, ValueType{0},
|
||||||
|
custom_bop_t());
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, ValueType{1},
|
||||||
|
custom_bop_t());
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, ValueType{-2},
|
||||||
|
custom_bop_t());
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, ValueType{3},
|
||||||
|
custom_bop_t());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_numeric_ops_test, exclusive_scan) {
|
||||||
|
run_exclusive_scan_all_scenarios<DynamicTag, double>();
|
||||||
|
run_exclusive_scan_all_scenarios<StridedThreeTag, double>();
|
||||||
|
run_exclusive_scan_all_scenarios<DynamicTag, int>();
|
||||||
|
run_exclusive_scan_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace EScan
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
191
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsFind.cpp
Normal file
191
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsFind.cpp
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <iterator>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Find {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_find(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
using view_host_space_t = Kokkos::View<value_t*, Kokkos::HostSpace>;
|
||||||
|
|
||||||
|
view_host_space_t expected("count_expected", view.extent(0));
|
||||||
|
compare_views(expected, view);
|
||||||
|
constexpr value_t find_value = 13;
|
||||||
|
|
||||||
|
// value not found, return last
|
||||||
|
EXPECT_EQ(KE::end(expected),
|
||||||
|
std::find(KE::begin(expected), KE::end(expected), find_value));
|
||||||
|
|
||||||
|
// pass const iterators, returns const iterator
|
||||||
|
EXPECT_EQ(KE::cend(view),
|
||||||
|
KE::find(exespace(), KE::cbegin(view), KE::cend(view), find_value));
|
||||||
|
// pass view, returns iterator
|
||||||
|
EXPECT_EQ(KE::end(view), KE::find(exespace(), view, find_value));
|
||||||
|
|
||||||
|
fill_views_inc(view, expected);
|
||||||
|
|
||||||
|
auto std_result =
|
||||||
|
std::find(KE::begin(expected), KE::end(expected), find_value);
|
||||||
|
auto distance = std::distance(KE::begin(expected), std_result);
|
||||||
|
|
||||||
|
// pass iterators, returns iterator
|
||||||
|
EXPECT_EQ(KE::begin(view) + distance,
|
||||||
|
KE::find(exespace(), KE::begin(view), KE::end(view), find_value));
|
||||||
|
// pass view, returns iterator
|
||||||
|
EXPECT_EQ(KE::begin(view) + distance, KE::find(exespace(), view, find_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_find_if(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
using view_host_space_t = Kokkos::View<value_t*, Kokkos::HostSpace>;
|
||||||
|
|
||||||
|
view_host_space_t expected("count_expected", view.extent(0));
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
const auto not_equals_zero = NotEqualsZeroFunctor<value_type>();
|
||||||
|
|
||||||
|
// value not found, return last
|
||||||
|
EXPECT_EQ(
|
||||||
|
KE::end(expected),
|
||||||
|
std::find_if(KE::begin(expected), KE::end(expected), not_equals_zero));
|
||||||
|
|
||||||
|
// pass iterators, returns iterator
|
||||||
|
EXPECT_EQ(KE::end(view), KE::find_if(exespace(), KE::begin(view),
|
||||||
|
KE::end(view), not_equals_zero));
|
||||||
|
// pass view, returns iterator
|
||||||
|
EXPECT_EQ(KE::end(view), KE::find_if(exespace(), view, not_equals_zero));
|
||||||
|
|
||||||
|
fill_views_inc(view, expected);
|
||||||
|
|
||||||
|
constexpr value_t find_value = 13;
|
||||||
|
const auto equals_val = EqualsValFunctor<value_type>(find_value);
|
||||||
|
auto std_result =
|
||||||
|
std::find_if(KE::begin(expected), KE::end(expected), equals_val);
|
||||||
|
auto distance = std::distance(KE::begin(expected), std_result);
|
||||||
|
|
||||||
|
// pass const iterators, returns const iterator
|
||||||
|
EXPECT_EQ(
|
||||||
|
KE::cbegin(view) + distance,
|
||||||
|
KE::find_if(exespace(), KE::cbegin(view), KE::cend(view), equals_val));
|
||||||
|
// pass view, returns iterator
|
||||||
|
EXPECT_EQ(KE::begin(view) + distance,
|
||||||
|
KE::find_if(exespace(), view, equals_val));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_find_if_not(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
using view_host_space_t = Kokkos::View<value_t*, Kokkos::HostSpace>;
|
||||||
|
|
||||||
|
view_host_space_t expected("count_expected", view.extent(0));
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
const auto not_equals_zero = NotEqualsZeroFunctor<value_type>();
|
||||||
|
|
||||||
|
// first value matches
|
||||||
|
EXPECT_EQ(KE::begin(expected),
|
||||||
|
std::find_if_not(KE::begin(expected), KE::end(expected),
|
||||||
|
not_equals_zero));
|
||||||
|
|
||||||
|
// pass iterators, returns iterator
|
||||||
|
EXPECT_EQ(KE::begin(view), KE::find_if_not(exespace(), KE::begin(view),
|
||||||
|
KE::end(view), not_equals_zero));
|
||||||
|
// pass view, returns iterator
|
||||||
|
EXPECT_EQ(KE::begin(view),
|
||||||
|
KE::find_if_not(exespace(), view, not_equals_zero));
|
||||||
|
|
||||||
|
fill_views_inc(view, expected);
|
||||||
|
|
||||||
|
const auto equals_zero = EqualsValFunctor<value_type>(0);
|
||||||
|
auto std_result =
|
||||||
|
std::find_if_not(KE::begin(expected), KE::end(expected), equals_zero);
|
||||||
|
auto distance = std::distance(KE::begin(expected), std_result);
|
||||||
|
|
||||||
|
// pass const iterators, returns const iterator
|
||||||
|
EXPECT_EQ(KE::cbegin(view) + distance,
|
||||||
|
KE::find_if_not(exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
equals_zero));
|
||||||
|
// pass view, returns const iterator
|
||||||
|
EXPECT_EQ(KE::begin(view) + distance,
|
||||||
|
KE::find_if_not(exespace(), view, equals_zero));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
for (const auto& scenario : default_scenarios) {
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "find");
|
||||||
|
test_find(view);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "find_if");
|
||||||
|
test_find_if(view);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "find_if_not");
|
||||||
|
test_find_if_not(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_find_test, test) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedTwoTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, unsigned>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Find
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
387
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsFindEnd.cpp
Normal file
387
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsFindEnd.cpp
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace FindEnd {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(0, 20) { m_gen.seed(1034343); }
|
||||||
|
UnifDist(int a, int b) : m_dist(a, b) { m_gen.seed(234343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "three-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(-1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
v_h(2) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "three-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(3);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "four-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(-1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
v_h(2) = static_cast<value_type>(2);
|
||||||
|
v_h(3) = static_cast<value_type>(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "four-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(0);
|
||||||
|
v_h(1) = static_cast<value_type>(4);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(-1);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(1);
|
||||||
|
v_h(7) = static_cast<value_type>(2);
|
||||||
|
v_h(8) = static_cast<value_type>(2);
|
||||||
|
v_h(9) = static_cast<value_type>(4);
|
||||||
|
v_h(10) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
v_h(2) = static_cast<value_type>(3);
|
||||||
|
v_h(3) = static_cast<value_type>(1);
|
||||||
|
v_h(4) = static_cast<value_type>(-1);
|
||||||
|
v_h(5) = static_cast<value_type>(-2);
|
||||||
|
v_h(6) = static_cast<value_type>(0);
|
||||||
|
v_h(7) = static_cast<value_type>(1);
|
||||||
|
v_h(8) = static_cast<value_type>(2);
|
||||||
|
v_h(9) = static_cast<value_type>(2);
|
||||||
|
v_h(10) = static_cast<value_type>(5);
|
||||||
|
v_h(11) = static_cast<value_type>(9);
|
||||||
|
v_h(12) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
auto create_seq(ViewType data_view, std::size_t seq_extent) {
|
||||||
|
// we need to specify a sequence that we search for
|
||||||
|
// within the original view/range.
|
||||||
|
// to do this, rather than doing something purely random,
|
||||||
|
// we use the view with the data, and select a subsequence.
|
||||||
|
|
||||||
|
auto data_view_h = create_host_space_copy(data_view);
|
||||||
|
const auto data_view_extent = data_view.extent(0);
|
||||||
|
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
using seq_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
seq_view_t seq_view("seq_view", seq_extent);
|
||||||
|
auto seq_view_h = create_mirror_view(Kokkos::HostSpace(), seq_view);
|
||||||
|
|
||||||
|
// when the target sequence is of same size as view, just fill
|
||||||
|
// sequeunce with all values of the view
|
||||||
|
if (seq_extent == data_view_extent) {
|
||||||
|
for (std::size_t i = 0; i < seq_extent; ++i) {
|
||||||
|
seq_view_h(i) = data_view_h(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if target sequence to fill is smaller, then we need to pick
|
||||||
|
// a starting point to copy data from to make the the sequence.
|
||||||
|
// we pick randomly between 0 and data_view_extent - seq_extent.
|
||||||
|
// and fill the sequeunce data with the values copied from data view.
|
||||||
|
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::random_device r;
|
||||||
|
// from this:
|
||||||
|
// https://stackoverflow.com/questions/34490599/c11-how-to-set-seed-using-random
|
||||||
|
std::seed_seq seed{r(), r(), r(), r(), r(), r()};
|
||||||
|
std::mt19937 gen(seed);
|
||||||
|
dist_type dist(0, data_view_extent - seq_extent);
|
||||||
|
const auto start = dist(gen);
|
||||||
|
// std::cout << "start= " << start << "\n";
|
||||||
|
for (std::size_t i = 0; i < seq_extent; ++i) {
|
||||||
|
seq_view_h(i) = data_view_h(start + i);
|
||||||
|
// std::cout << "i= " << i << " " << seq_view_h(i) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(seq_view, seq_view_h);
|
||||||
|
return seq_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search is only avai from c++17, so I have to put it here
|
||||||
|
template <class ForwardIt1, class ForwardIt2, class BinaryPredicate>
|
||||||
|
ForwardIt1 my_std_search(ForwardIt1 first, ForwardIt1 last, ForwardIt2 s_first,
|
||||||
|
ForwardIt2 s_last, BinaryPredicate p) {
|
||||||
|
for (;; ++first) {
|
||||||
|
ForwardIt1 it = first;
|
||||||
|
for (ForwardIt2 s_it = s_first;; ++it, ++s_it) {
|
||||||
|
if (s_it == s_last) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
if (it == last) {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
if (!p(*it, *s_it)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only avai from c++17, so I have to put it here
|
||||||
|
template <class ForwardIt1, class ForwardIt2, class BinaryPredicate>
|
||||||
|
ForwardIt1 my_std_find_end(ForwardIt1 first, ForwardIt1 last,
|
||||||
|
ForwardIt2 s_first, ForwardIt2 s_last,
|
||||||
|
BinaryPredicate p) {
|
||||||
|
if (s_first == s_last) {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
ForwardIt1 result = last;
|
||||||
|
while (true) {
|
||||||
|
ForwardIt1 new_result = my_std_search(first, last, s_first, s_last, p);
|
||||||
|
if (new_result == last) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
result = new_result;
|
||||||
|
first = result;
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ForwardIt1, class ForwardIt2>
|
||||||
|
ForwardIt1 my_std_find_end(ForwardIt1 first, ForwardIt1 last,
|
||||||
|
ForwardIt2 s_first, ForwardIt2 s_last) {
|
||||||
|
using value_type1 = typename ForwardIt1::value_type;
|
||||||
|
using value_type2 = typename ForwardIt2::value_type;
|
||||||
|
|
||||||
|
using pred_t = IsEqualFunctor<value_type1, value_type2>;
|
||||||
|
return my_std_find_end(first, last, s_first, s_last, pred_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t seq_ext) {
|
||||||
|
std::cout << "find_end: default predicate: " << name << ", "
|
||||||
|
<< "find_end_seq_ext = " << seq_ext << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class Predicate>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t seq_ext,
|
||||||
|
Predicate pred) {
|
||||||
|
(void)pred;
|
||||||
|
std::cout << "find_end: custom predicate: " << name << ", "
|
||||||
|
<< "find_end_seq_ext = " << seq_ext << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class... Args>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info, std::size_t seq_ext,
|
||||||
|
Args... args) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, seq_ext, args...);
|
||||||
|
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "find_end_test_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
auto s_view = create_seq(view, seq_ext);
|
||||||
|
|
||||||
|
// run std
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto s_view_h = create_host_space_copy(s_view);
|
||||||
|
auto stdrit =
|
||||||
|
my_std_find_end(KE::cbegin(view_h), KE::cend(view_h),
|
||||||
|
KE::cbegin(s_view_h), KE::cend(s_view_h), args...);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::find_end(exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::cbegin(s_view), KE::cend(s_view), args...);
|
||||||
|
const auto mydiff = myrit - KE::cbegin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
// std::cout << "result : " << mydiff << " " << stddiff << std::endl;
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit =
|
||||||
|
KE::find_end("label", exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::cbegin(s_view), KE::cend(s_view), args...);
|
||||||
|
const auto mydiff = myrit - KE::cbegin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::find_end(exespace(), view, s_view, args...);
|
||||||
|
const auto mydiff = myrit - KE::begin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::find_end("label", exespace(), view, s_view, args...);
|
||||||
|
const auto mydiff = myrit - KE::begin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {{"empty", 0},
|
||||||
|
{"one-element-a", 1},
|
||||||
|
{"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2},
|
||||||
|
{"three-elements-a", 3},
|
||||||
|
{"three-elements-b", 3},
|
||||||
|
{"four-elements-a", 4},
|
||||||
|
{"four-elements-b", 4},
|
||||||
|
{"small-a", 11},
|
||||||
|
{"small-b", 13},
|
||||||
|
{"medium-a", 11103},
|
||||||
|
{"medium-b", 21103},
|
||||||
|
{"large-a", 101513},
|
||||||
|
{"large-b", 100111}};
|
||||||
|
|
||||||
|
const std::vector<std::size_t> seq_extents = {
|
||||||
|
0, 1, 2, 3, 4, 5, 8, 11, 15, 31, 113, 523, 1035, 11103};
|
||||||
|
|
||||||
|
// for each scenario we want to run "find_end"
|
||||||
|
// for a set of sequences of various extents
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
for (const auto& it2 : seq_extents) {
|
||||||
|
// only run if view is larger or equal than sequence
|
||||||
|
if (it.second >= it2) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2);
|
||||||
|
|
||||||
|
using func_t = IsEqualFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2, func_t());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_non_mod_seq_ops, find_end) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace FindEnd
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,303 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace FindFirstOf {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-100, 100) { m_gen.seed(1034343); }
|
||||||
|
UnifDist(int a, int b) : m_dist(a, b) { m_gen.seed(514343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "three-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(-1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
v_h(2) = static_cast<value_type>(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "three-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(3);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "four-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(-1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
v_h(2) = static_cast<value_type>(2);
|
||||||
|
v_h(3) = static_cast<value_type>(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "four-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(0);
|
||||||
|
v_h(1) = static_cast<value_type>(4);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(-1);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(1);
|
||||||
|
v_h(7) = static_cast<value_type>(2);
|
||||||
|
v_h(8) = static_cast<value_type>(2);
|
||||||
|
v_h(9) = static_cast<value_type>(4);
|
||||||
|
v_h(10) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
v_h(2) = static_cast<value_type>(3);
|
||||||
|
v_h(3) = static_cast<value_type>(1);
|
||||||
|
v_h(4) = static_cast<value_type>(-1);
|
||||||
|
v_h(5) = static_cast<value_type>(-2);
|
||||||
|
v_h(6) = static_cast<value_type>(0);
|
||||||
|
v_h(7) = static_cast<value_type>(1);
|
||||||
|
v_h(8) = static_cast<value_type>(2);
|
||||||
|
v_h(9) = static_cast<value_type>(2);
|
||||||
|
v_h(10) = static_cast<value_type>(5);
|
||||||
|
v_h(11) = static_cast<value_type>(9);
|
||||||
|
v_h(12) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
auto create_seq_for_find_first_of(ViewType data_view, std::size_t seq_extent) {
|
||||||
|
(void)data_view;
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
using seq_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
seq_view_t seq_view("seq_view", seq_extent);
|
||||||
|
auto seq_view_h = create_mirror_view(Kokkos::HostSpace(), seq_view);
|
||||||
|
|
||||||
|
UnifDist<value_type> randObj(-10, -10);
|
||||||
|
for (std::size_t i = 0; i < seq_extent; ++i) {
|
||||||
|
seq_view_h(i) = randObj();
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(seq_view, seq_view_h);
|
||||||
|
return seq_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t seq_ext) {
|
||||||
|
std::cout << "find_first_of: default predicate: " << name << ", "
|
||||||
|
<< "seach_seq_ext = " << seq_ext << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class Predicate>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t seq_ext,
|
||||||
|
Predicate pred) {
|
||||||
|
(void)pred;
|
||||||
|
std::cout << "find_first_of: custom predicate: " << name << ", "
|
||||||
|
<< "seach_seq_ext = " << seq_ext << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class... Args>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info, std::size_t seq_ext,
|
||||||
|
Args... args) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, seq_ext, args...);
|
||||||
|
|
||||||
|
auto view =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "find_first_of_test_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
auto s_view = create_seq_for_find_first_of(view, seq_ext);
|
||||||
|
|
||||||
|
// run std
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto s_view_h = create_host_space_copy(s_view);
|
||||||
|
auto stdrit =
|
||||||
|
std::find_first_of(KE::cbegin(view_h), KE::cend(view_h),
|
||||||
|
KE::cbegin(s_view_h), KE::cend(s_view_h), args...);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit =
|
||||||
|
KE::find_first_of(exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::cbegin(s_view), KE::cend(s_view), args...);
|
||||||
|
const auto mydiff = myrit - KE::cbegin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit =
|
||||||
|
KE::find_first_of("label", exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::cbegin(s_view), KE::cend(s_view), args...);
|
||||||
|
const auto mydiff = myrit - KE::cbegin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::find_first_of(exespace(), view, s_view, args...);
|
||||||
|
const auto mydiff = myrit - KE::begin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::find_first_of("label", exespace(), view, s_view, args...);
|
||||||
|
const auto mydiff = myrit - KE::begin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {{"empty", 0},
|
||||||
|
{"one-element-a", 1},
|
||||||
|
{"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2},
|
||||||
|
{"three-elements-a", 3},
|
||||||
|
{"three-elements-b", 3},
|
||||||
|
{"four-elements-a", 4},
|
||||||
|
{"four-elements-b", 4},
|
||||||
|
{"small-a", 11},
|
||||||
|
{"small-b", 13},
|
||||||
|
{"medium-a", 11103},
|
||||||
|
{"medium-b", 21103},
|
||||||
|
{"large-a", 101513},
|
||||||
|
{"large-b", 100111}};
|
||||||
|
|
||||||
|
const std::vector<std::size_t> seq_extents = {0, 1, 2, 3, 4, 5, 8,
|
||||||
|
11, 20, 31, 113, 523, 1035};
|
||||||
|
|
||||||
|
// for each scenario we want to run "find_first_of"
|
||||||
|
// for a set of sequences of various extents
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
for (const auto& it2 : seq_extents) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2);
|
||||||
|
|
||||||
|
using func_t = IsEqualFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2, func_t());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_non_mod_seq_ops, find_first_of) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace FindFirstOf
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
167
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsForEach.cpp
Normal file
167
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsForEach.cpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace ForEach {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_for_each(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
using view_host_space_t = Kokkos::View<value_t*, Kokkos::HostSpace>;
|
||||||
|
|
||||||
|
view_host_space_t expected("for_each_expected", view.extent(0));
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
const auto mod_functor = IncrementElementWiseFunctor<value_t>();
|
||||||
|
|
||||||
|
// pass view, functor takes non-const ref
|
||||||
|
KE::for_each("label", exespace(), view, mod_functor);
|
||||||
|
std::for_each(KE::begin(expected), KE::end(expected), mod_functor);
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
// pass iterators, functor takes non-const ref
|
||||||
|
KE::for_each(exespace(), KE::begin(view), KE::end(view), mod_functor);
|
||||||
|
std::for_each(KE::begin(expected), KE::end(expected), mod_functor);
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
const auto non_mod_functor = NoOpNonMutableFunctor<value_t>();
|
||||||
|
|
||||||
|
// pass view, functor takes const ref
|
||||||
|
KE::for_each(exespace(), view, non_mod_functor);
|
||||||
|
std::for_each(KE::begin(expected), KE::end(expected), non_mod_functor);
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
// pass const iterators, functor takes const ref
|
||||||
|
KE::for_each(exespace(), KE::cbegin(view), KE::cend(view), non_mod_functor);
|
||||||
|
std::for_each(KE::begin(expected), KE::end(expected), non_mod_functor);
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
#if defined(KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA)
|
||||||
|
const auto mod_lambda = KOKKOS_LAMBDA(value_t & i) { ++i; };
|
||||||
|
|
||||||
|
// pass view, lambda takes non-const ref
|
||||||
|
KE::for_each(exespace(), view, mod_lambda);
|
||||||
|
std::for_each(KE::begin(expected), KE::end(expected), mod_lambda);
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
// pass iterators, lambda takes non-const ref
|
||||||
|
KE::for_each(exespace(), KE::begin(view), KE::end(view), mod_lambda);
|
||||||
|
std::for_each(KE::begin(expected), KE::end(expected), mod_lambda);
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
const auto non_mod_lambda = KOKKOS_LAMBDA(const value_t& i) { (void)i; };
|
||||||
|
|
||||||
|
// pass view, lambda takes const ref
|
||||||
|
KE::for_each(exespace(), view, non_mod_lambda);
|
||||||
|
std::for_each(KE::cbegin(expected), KE::cend(expected), non_mod_lambda);
|
||||||
|
compare_views(expected, view);
|
||||||
|
|
||||||
|
// pass const iterators, lambda takes const ref
|
||||||
|
KE::for_each(exespace(), KE::cbegin(view), KE::cend(view), non_mod_lambda);
|
||||||
|
std::for_each(KE::cbegin(expected), KE::cend(expected), non_mod_lambda);
|
||||||
|
compare_views(expected, view);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::for_each_n is C++17, so we cannot compare results directly
|
||||||
|
template <class ViewType>
|
||||||
|
void test_for_each_n(const ViewType view) {
|
||||||
|
using value_t = typename ViewType::value_type;
|
||||||
|
const std::size_t n = view.extent(0);
|
||||||
|
|
||||||
|
const auto non_mod_functor = NoOpNonMutableFunctor<value_t>();
|
||||||
|
|
||||||
|
// pass const iterators, functor takes const ref
|
||||||
|
EXPECT_EQ(KE::cbegin(view) + n,
|
||||||
|
KE::for_each_n(exespace(), KE::cbegin(view), n, non_mod_functor));
|
||||||
|
verify_values(value_t{0}, view);
|
||||||
|
|
||||||
|
// pass view, functor takes const ref
|
||||||
|
EXPECT_EQ(KE::begin(view) + n,
|
||||||
|
KE::for_each_n(exespace(), view, n, non_mod_functor));
|
||||||
|
verify_values(value_t{0}, view);
|
||||||
|
|
||||||
|
// pass iterators, functor takes non-const ref
|
||||||
|
const auto mod_functor = IncrementElementWiseFunctor<value_t>();
|
||||||
|
EXPECT_EQ(KE::begin(view) + n,
|
||||||
|
KE::for_each_n(exespace(), KE::begin(view), n, mod_functor));
|
||||||
|
verify_values(value_t{1}, view);
|
||||||
|
|
||||||
|
// pass view, functor takes non-const ref
|
||||||
|
EXPECT_EQ(KE::begin(view) + n,
|
||||||
|
KE::for_each_n("label", exespace(), view, n, mod_functor));
|
||||||
|
verify_values(value_t{2}, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
for (const auto& scenario : default_scenarios) {
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "for_each");
|
||||||
|
test_for_each(view);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, scenario.second, "for_each_n");
|
||||||
|
test_for_each_n(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_for_each_test, test) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedTwoTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, unsigned>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ForEach
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KOKKOS_ALGORITHMS_UNITTESTS_TEST_STD_ALGOS_HELPERS_FUNCTORS_HPP
|
||||||
|
#define KOKKOS_ALGORITHMS_UNITTESTS_TEST_STD_ALGOS_HELPERS_FUNCTORS_HPP
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
template <class ViewTypeFrom, class ViewTypeTo>
|
||||||
|
struct CopyFunctor {
|
||||||
|
ViewTypeFrom m_view_from;
|
||||||
|
ViewTypeTo m_view_to;
|
||||||
|
|
||||||
|
CopyFunctor() = delete;
|
||||||
|
|
||||||
|
CopyFunctor(const ViewTypeFrom view_from, const ViewTypeTo view_to)
|
||||||
|
: m_view_from(view_from), m_view_to(view_to) {}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(int i) const { m_view_to(i) = m_view_from(i); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ItTypeFrom, class ViewTypeTo>
|
||||||
|
struct CopyFromIteratorFunctor {
|
||||||
|
ItTypeFrom m_it_from;
|
||||||
|
ViewTypeTo m_view_to;
|
||||||
|
|
||||||
|
CopyFromIteratorFunctor(const ItTypeFrom it_from, const ViewTypeTo view_to)
|
||||||
|
: m_it_from(it_from), m_view_to(view_to) {}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(int) const { m_view_to() = *m_it_from; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct IncrementElementWiseFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(ValueType& val) const { ++val; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
struct FillZeroFunctor {
|
||||||
|
ViewType m_view;
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(int index) const {
|
||||||
|
m_view(index) = static_cast<typename ViewType::value_type>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
FillZeroFunctor(ViewType viewIn) : m_view(viewIn) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct NoOpNonMutableFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(const ValueType& val) const { (void)val; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
struct AssignIndexFunctor {
|
||||||
|
ViewType m_view;
|
||||||
|
|
||||||
|
AssignIndexFunctor(ViewType view) : m_view(view) {}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(int i) const { m_view(i) = typename ViewType::value_type(i); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct IsEvenFunctor {
|
||||||
|
static_assert(std::is_integral<ValueType>::value,
|
||||||
|
"IsEvenFunctor uses operator%, so ValueType must be int");
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType val) const { return (val % 2 == 0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct IsPositiveFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType val) const { return (val > 0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct IsNegativeFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType val) const { return (val < 0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct NotEqualsZeroFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType val) const { return val != 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct EqualsValFunctor {
|
||||||
|
const ValueType m_value;
|
||||||
|
|
||||||
|
EqualsValFunctor(ValueType value) : m_value(value) {}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType val) const { return val == m_value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType1, class ValueType2>
|
||||||
|
struct CustomLessThanComparator {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType1& a, const ValueType2& b) const {
|
||||||
|
return a < b;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const volatile ValueType1& a,
|
||||||
|
const volatile ValueType1& b) const {
|
||||||
|
return a < b;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
CustomLessThanComparator() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct CustomEqualityComparator {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType1, class ValueType2 = ValueType1>
|
||||||
|
struct IsEqualFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType1& a, const ValueType2& b) const {
|
||||||
|
return (a == b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,390 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_Numeric.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace IncScan {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(0.05, 1.2) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(1, 3) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_zero(ViewType view) {
|
||||||
|
Kokkos::parallel_for(view.extent(0), FillZeroFunctor<ViewType>(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
v_h(5) = static_cast<value_type>(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium-a" || name == "medium-b" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// my own because std::inclusive_scan is ONLY found with std=c++17
|
||||||
|
template <class it1, class it2, class BinOp>
|
||||||
|
void my_host_inclusive_scan(it1 first, it1 last, it2 dest, BinOp bop) {
|
||||||
|
if (first != last) {
|
||||||
|
auto init = *first;
|
||||||
|
*dest = init;
|
||||||
|
while (++first < last) {
|
||||||
|
init = bop(*first, init);
|
||||||
|
*(++dest) = init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class it1, class it2, class BinOp, class ValType>
|
||||||
|
void my_host_inclusive_scan(it1 first, it1 last, it2 dest, BinOp bop,
|
||||||
|
ValType init) {
|
||||||
|
if (first != last) {
|
||||||
|
init = bop(*first, init);
|
||||||
|
*dest = init;
|
||||||
|
while (++first < last) {
|
||||||
|
init = bop(*first, init);
|
||||||
|
*(++dest) = init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2, class BinaryOp, class... Args>
|
||||||
|
void verify_data(ViewType1 data_view, // contains data
|
||||||
|
ViewType2 test_view, // the view to test
|
||||||
|
BinaryOp bop, Args... args /* copy on purpose */) {
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
|
||||||
|
auto data_view_dc = create_deep_copyable_compatible_clone(data_view);
|
||||||
|
auto data_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), data_view_dc);
|
||||||
|
|
||||||
|
using gold_view_value_type = typename ViewType2::value_type;
|
||||||
|
Kokkos::View<gold_view_value_type*, Kokkos::HostSpace> gold_h(
|
||||||
|
"goldh", data_view.extent(0));
|
||||||
|
my_host_inclusive_scan(KE::cbegin(data_view_h), KE::cend(data_view_h),
|
||||||
|
KE::begin(gold_h), bop, args...);
|
||||||
|
|
||||||
|
auto test_view_dc = create_deep_copyable_compatible_clone(test_view);
|
||||||
|
auto test_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), test_view_dc);
|
||||||
|
|
||||||
|
const auto ext = test_view_h.extent(0);
|
||||||
|
if (ext > 0) {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
// std::cout << i << " " << std::setprecision(15) << data_view_h(i) << " "
|
||||||
|
// << gold_h(i) << " " << test_view_h(i) << " "
|
||||||
|
// << std::abs(gold_h(i) - test_view_h(i)) << std::endl;
|
||||||
|
|
||||||
|
if (std::is_same<gold_view_value_type, int>::value) {
|
||||||
|
EXPECT_TRUE(gold_h(i) == test_view_h(i));
|
||||||
|
} else {
|
||||||
|
const auto error = std::abs(gold_h(i) - test_view_h(i));
|
||||||
|
if (error > 1e-10) {
|
||||||
|
std::cout << i << " " << std::setprecision(15) << data_view_h(i)
|
||||||
|
<< " " << gold_h(i) << " " << test_view_h(i) << " "
|
||||||
|
<< std::abs(gold_h(i) - test_view_h(i)) << std::endl;
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(error < 1e-10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// std::cout << " last el: " << test_view_h(ext-1) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct MultiplyFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return (a * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const volatile ValueType& a,
|
||||||
|
const volatile ValueType& b) const {
|
||||||
|
return (a * b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct SumFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const volatile ValueType& a,
|
||||||
|
const volatile ValueType& b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario_default_op(const InfoType& scenario_info) {
|
||||||
|
using default_op = SumFunctor<ValueType>;
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "inclusive_scan default op: " << name << ", "
|
||||||
|
// << view_tag_to_string(Tag{}) << ", "
|
||||||
|
// << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
auto view_dest = create_view<ValueType>(Tag{}, view_ext, "inclusive_scan");
|
||||||
|
auto view_from = create_view<ValueType>(Tag{}, view_ext, "inclusive_scan");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::inclusive_scan(exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest));
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, default_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::inclusive_scan("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest));
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, default_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::inclusive_scan(exespace(), view_from, view_dest);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, default_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::inclusive_scan("label", exespace(), view_from, view_dest);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, default_op());
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class BinaryOp,
|
||||||
|
class... Args>
|
||||||
|
void run_single_scenario_custom_op(const InfoType& scenario_info, BinaryOp bop,
|
||||||
|
Args... args /* copy on purpose */) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
|
||||||
|
// if (1 == sizeof...(Args)) {
|
||||||
|
// std::cout << "inclusive_scan custom op and init value: " << name << ", "
|
||||||
|
// << view_tag_to_string(Tag{}) << ", "
|
||||||
|
// << value_type_to_string(ValueType()) << ", " << std::endl;
|
||||||
|
// } else {
|
||||||
|
// std::cout << "inclusive_scan custom op: " << name << ", "
|
||||||
|
// << view_tag_to_string(Tag{}) << ", "
|
||||||
|
// << value_type_to_string(ValueType()) << ", " << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
|
auto view_dest = create_view<ValueType>(Tag{}, view_ext, "inclusive_scan");
|
||||||
|
auto view_from = create_view<ValueType>(Tag{}, view_ext, "inclusive_scan");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::inclusive_scan(exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest), bop,
|
||||||
|
args...);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, bop, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::inclusive_scan("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest), bop,
|
||||||
|
args...);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, bop, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::inclusive_scan(exespace(), view_from, view_dest, bop, args...);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, bop, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::inclusive_scan("label", exespace(), view_from, view_dest, bop,
|
||||||
|
args...);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, bop, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_inclusive_scan_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element", 1}, {"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2}, {"small-a", 9}, {"small-b", 13},
|
||||||
|
{"medium-a", 313}, {"medium-b", 1103}, {"large", 10513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario_default_op<Tag, ValueType>(it);
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
// the sum custom op is always run
|
||||||
|
using sum_binary_op = SumFunctor<ValueType>;
|
||||||
|
sum_binary_op sbop;
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, sbop);
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, sbop, ValueType{0});
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, sbop, ValueType{1});
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, sbop, ValueType{-2});
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, sbop, ValueType{3});
|
||||||
|
|
||||||
|
// custom multiply only for small views to avoid overflows
|
||||||
|
if (it.first == "small-a" || it.first == "small-b") {
|
||||||
|
using mult_binary_op = MultiplyFunctor<ValueType>;
|
||||||
|
mult_binary_op mbop;
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, mbop);
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, mbop, ValueType{0});
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, mbop, ValueType{1});
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, mbop, ValueType{-2});
|
||||||
|
run_single_scenario_custom_op<Tag, ValueType>(it, mbop, ValueType{3});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_numeric_ops_test, inclusive_scan) {
|
||||||
|
run_inclusive_scan_all_scenarios<DynamicTag, double>();
|
||||||
|
run_inclusive_scan_all_scenarios<StridedThreeTag, double>();
|
||||||
|
run_inclusive_scan_all_scenarios<DynamicTag, int>();
|
||||||
|
run_inclusive_scan_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace IncScan
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
222
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSorted.cpp
Normal file
222
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsIsSorted.cpp
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_SortingOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace IsSorted {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
v_h(5) = static_cast<value_type>(-15);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
v_h(4) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(-100) + static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(-100) + static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
v_h(156) = static_cast<value_type>(-250);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compute_gold(const std::string& name) {
|
||||||
|
if (name == "empty") {
|
||||||
|
return true;
|
||||||
|
} else if (name == "one-element") {
|
||||||
|
return true;
|
||||||
|
} else if (name == "two-elements-a") {
|
||||||
|
return true;
|
||||||
|
} else if (name == "two-elements-b") {
|
||||||
|
return false;
|
||||||
|
} else if (name == "small-a") {
|
||||||
|
return true;
|
||||||
|
} else if (name == "small-b") {
|
||||||
|
return false;
|
||||||
|
} else if (name == "medium-a") {
|
||||||
|
return true;
|
||||||
|
} else if (name == "medium-b") {
|
||||||
|
return false;
|
||||||
|
} else if (name == "large-a") {
|
||||||
|
return true;
|
||||||
|
} else if (name == "large-b") {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
|
||||||
|
// std::cout << "is-sorted: " << name << ", " << view_tag_to_string(Tag{})
|
||||||
|
// << std::endl;
|
||||||
|
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "is_sorted");
|
||||||
|
fill_view(view, name);
|
||||||
|
const auto gold = compute_gold(name);
|
||||||
|
|
||||||
|
std::vector<bool> resultsA(4);
|
||||||
|
resultsA[0] = KE::is_sorted(exespace(), KE::cbegin(view), KE::cend(view));
|
||||||
|
resultsA[1] =
|
||||||
|
KE::is_sorted("label", exespace(), KE::cbegin(view), KE::cend(view));
|
||||||
|
resultsA[2] = KE::is_sorted(exespace(), view);
|
||||||
|
resultsA[3] = KE::is_sorted("label", exespace(), view);
|
||||||
|
const auto allA = std::all_of(resultsA.cbegin(), resultsA.cend(),
|
||||||
|
[=](bool v) { return v == gold; });
|
||||||
|
EXPECT_TRUE(allA);
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
CustomLessThanComparator<ValueType, ValueType> comp;
|
||||||
|
std::vector<bool> resultsB(4);
|
||||||
|
resultsB[0] =
|
||||||
|
KE::is_sorted(exespace(), KE::cbegin(view), KE::cend(view), comp);
|
||||||
|
resultsB[1] = KE::is_sorted("label", exespace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), comp);
|
||||||
|
resultsB[2] = KE::is_sorted(exespace(), view, comp);
|
||||||
|
resultsB[3] = KE::is_sorted("label", exespace(), view, comp);
|
||||||
|
const auto allB = std::all_of(resultsB.cbegin(), resultsB.cend(),
|
||||||
|
[=](bool v) { return v == gold; });
|
||||||
|
EXPECT_TRUE(allB);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_is_sorted_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element", 1}, {"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2}, {"small-a", 9}, {"small-b", 13},
|
||||||
|
{"medium-a", 1003}, {"medium-b", 1003}, {"large-a", 101513},
|
||||||
|
{"large-b", 101513}};
|
||||||
|
|
||||||
|
std::cout << "is_sorted: " << view_tag_to_string(Tag{})
|
||||||
|
<< ", all overloads \n";
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_sorting_ops_test, is_sorted) {
|
||||||
|
run_is_sorted_all_scenarios<DynamicTag, double>();
|
||||||
|
run_is_sorted_all_scenarios<StridedTwoTag, double>();
|
||||||
|
run_is_sorted_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace IsSorted
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_SortingOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace IsSortedUntil {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
v_h(5) = static_cast<value_type>(15);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
v_h(4) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(-100) + static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(-100) + static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
v_h(156) = static_cast<value_type>(-250);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
auto compute_gold(ViewType view, const std::string& name) {
|
||||||
|
if (name == "empty") {
|
||||||
|
return KE::end(view);
|
||||||
|
} else if (name == "one-element") {
|
||||||
|
return KE::end(view);
|
||||||
|
} else if (name == "two-elements-a") {
|
||||||
|
return KE::end(view);
|
||||||
|
} else if (name == "two-elements-b") {
|
||||||
|
return KE::begin(view) + 1;
|
||||||
|
} else if (name == "small-a") {
|
||||||
|
return KE::end(view);
|
||||||
|
} else if (name == "small-b") {
|
||||||
|
return KE::begin(view) + 6;
|
||||||
|
} else if (name == "medium-a") {
|
||||||
|
return KE::end(view);
|
||||||
|
} else if (name == "medium-b") {
|
||||||
|
return KE::begin(view) + 4;
|
||||||
|
} else if (name == "large-a") {
|
||||||
|
return KE::end(view);
|
||||||
|
} else if (name == "large-b") {
|
||||||
|
return KE::begin(view) + 156;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
|
||||||
|
// std::cout << "is-sorted-until: " << name << ", " <<
|
||||||
|
// view_tag_to_string(Tag{})
|
||||||
|
// << std::endl;
|
||||||
|
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "is_sorted_until");
|
||||||
|
fill_view(view, name);
|
||||||
|
const auto gold = compute_gold(view, name);
|
||||||
|
|
||||||
|
auto r1 = KE::is_sorted_until(exespace(), KE::begin(view), KE::end(view));
|
||||||
|
auto r2 =
|
||||||
|
KE::is_sorted_until("label", exespace(), KE::begin(view), KE::end(view));
|
||||||
|
auto r3 = KE::is_sorted_until(exespace(), view);
|
||||||
|
auto r4 = KE::is_sorted_until("label", exespace(), view);
|
||||||
|
EXPECT_TRUE(r1 == gold);
|
||||||
|
EXPECT_TRUE(r2 == gold);
|
||||||
|
EXPECT_TRUE(r3 == gold);
|
||||||
|
EXPECT_TRUE(r4 == gold);
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
CustomLessThanComparator<ValueType, ValueType> comp;
|
||||||
|
auto r5 =
|
||||||
|
KE::is_sorted_until(exespace(), KE::cbegin(view), KE::cend(view), comp);
|
||||||
|
auto r6 = KE::is_sorted_until("label", exespace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), comp);
|
||||||
|
auto r7 = KE::is_sorted_until(exespace(), view, comp);
|
||||||
|
auto r8 = KE::is_sorted_until("label", exespace(), view, comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXPECT_TRUE(r1 == gold);
|
||||||
|
EXPECT_TRUE(r2 == gold);
|
||||||
|
EXPECT_TRUE(r3 == gold);
|
||||||
|
EXPECT_TRUE(r4 == gold);
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_is_sorted_until_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element", 1}, {"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2}, {"small-a", 9}, {"small-b", 13},
|
||||||
|
{"medium-a", 1003}, {"medium-b", 1003}, {"large-a", 101513},
|
||||||
|
{"large-b", 101513}};
|
||||||
|
|
||||||
|
std::cout << "is_sorted_until: " << view_tag_to_string(Tag{})
|
||||||
|
<< ", all overloads \n";
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_sorting_ops_test, is_sorted_until) {
|
||||||
|
run_is_sorted_until_all_scenarios<DynamicTag, double>();
|
||||||
|
run_is_sorted_until_all_scenarios<StridedTwoTag, double>();
|
||||||
|
run_is_sorted_until_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace IsSortedUntil
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace LexicographicalCompare {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2>
|
||||||
|
void test_lexicographical_compare(const ViewType1 view_1, ViewType2 view_2) {
|
||||||
|
auto host_copy_1 = create_host_space_copy(view_1);
|
||||||
|
auto host_copy_2 = create_host_space_copy(view_2);
|
||||||
|
|
||||||
|
auto first_1 = KE::begin(view_1);
|
||||||
|
auto last_1 = KE::end(view_1);
|
||||||
|
auto first_2 = KE::begin(view_2);
|
||||||
|
auto last_2 = KE::end(view_2);
|
||||||
|
|
||||||
|
auto h_first_1 = KE::begin(host_copy_1);
|
||||||
|
auto h_last_1 = KE::end(host_copy_1);
|
||||||
|
auto h_first_2 = KE::begin(host_copy_2);
|
||||||
|
auto h_last_2 = KE::end(host_copy_2);
|
||||||
|
|
||||||
|
{
|
||||||
|
// default comparator
|
||||||
|
auto std_result =
|
||||||
|
std::lexicographical_compare(h_first_1, h_last_1, h_first_2, h_last_2);
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_EQ(std_result, KE::lexicographical_compare(exespace(), first_1,
|
||||||
|
last_1, first_2, last_2));
|
||||||
|
EXPECT_EQ(std_result,
|
||||||
|
KE::lexicographical_compare("label", exespace(), first_1, last_1,
|
||||||
|
first_2, last_2));
|
||||||
|
|
||||||
|
// pass views
|
||||||
|
EXPECT_EQ(std_result,
|
||||||
|
KE::lexicographical_compare(exespace(), view_1, view_2));
|
||||||
|
EXPECT_EQ(std_result,
|
||||||
|
KE::lexicographical_compare("label", exespace(), view_1, view_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// custom comparator
|
||||||
|
using value_t_1 = typename ViewType1::value_type;
|
||||||
|
using value_t_2 = typename ViewType2::value_type;
|
||||||
|
const auto custom_comparator =
|
||||||
|
CustomLessThanComparator<value_t_1, value_t_2>();
|
||||||
|
auto std_result = std::lexicographical_compare(
|
||||||
|
h_first_1, h_last_1, h_first_2, h_last_2, custom_comparator);
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_EQ(std_result,
|
||||||
|
KE::lexicographical_compare(exespace(), first_1, last_1, first_2,
|
||||||
|
last_2, custom_comparator));
|
||||||
|
EXPECT_EQ(std_result,
|
||||||
|
KE::lexicographical_compare("label", exespace(), first_1, last_1,
|
||||||
|
first_2, last_2, custom_comparator));
|
||||||
|
|
||||||
|
// pass views
|
||||||
|
EXPECT_EQ(std_result, KE::lexicographical_compare(
|
||||||
|
exespace(), view_1, view_2, custom_comparator));
|
||||||
|
EXPECT_EQ(std_result,
|
||||||
|
KE::lexicographical_compare("label", exespace(), view_1, view_2,
|
||||||
|
custom_comparator));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// empty vs non-empty
|
||||||
|
auto std_result =
|
||||||
|
std::lexicographical_compare(h_first_1, h_first_1, h_first_2, h_last_2);
|
||||||
|
EXPECT_EQ(std_result, KE::lexicographical_compare(
|
||||||
|
exespace(), first_1, first_1, first_2, last_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// pass shorter range
|
||||||
|
if (view_1.extent(0) > 1) {
|
||||||
|
auto std_result = std::lexicographical_compare(h_first_1, h_last_1 - 1,
|
||||||
|
h_first_2, h_last_2);
|
||||||
|
EXPECT_EQ(std_result,
|
||||||
|
KE::lexicographical_compare(exespace(), first_1, last_1 - 1,
|
||||||
|
first_2, last_2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// first element smaller
|
||||||
|
if (view_1.extent(0) > 1) {
|
||||||
|
KE::fill(exespace(), first_1, first_1 + 1, 1);
|
||||||
|
KE::fill(exespace(), first_2, first_2 + 1, 2);
|
||||||
|
|
||||||
|
EXPECT_TRUE(KE::lexicographical_compare(exespace(), first_1, last_1,
|
||||||
|
first_2, last_2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// first element bigger, last element smaller
|
||||||
|
if (view_1.extent(0) > 2) {
|
||||||
|
KE::fill(exespace(), first_1, first_1 + 1, 2);
|
||||||
|
KE::fill(exespace(), first_2, first_2 + 1, 1);
|
||||||
|
|
||||||
|
KE::fill(exespace(), last_1 - 1, last_1, 1);
|
||||||
|
KE::fill(exespace(), last_2 - 1, last_2, 2);
|
||||||
|
|
||||||
|
EXPECT_FALSE(KE::lexicographical_compare(exespace(), first_1, last_1,
|
||||||
|
first_2, last_2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
for (const auto& scenario : default_scenarios) {
|
||||||
|
auto view1 = create_view<ValueType>(Tag{}, scenario.second,
|
||||||
|
"lexicographical_compare_1");
|
||||||
|
auto view2 = create_view<ValueType>(Tag{}, scenario.second,
|
||||||
|
"lexicographical_compare_2");
|
||||||
|
|
||||||
|
test_lexicographical_compare(view1, view2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_lexicographical_compare_test, test) {
|
||||||
|
// FIXME: should this disable only custom comparator tests?
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedTwoTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, unsigned>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace LexicographicalCompare
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,492 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_MinMaxElementOperations.hpp>
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
struct std_algorithms_min_max_element_test : std_algorithms_test {
|
||||||
|
const int m_number_of_filling_cases = 5;
|
||||||
|
|
||||||
|
void fillFixtureViews(int case_number) {
|
||||||
|
static_view_t tmpView("tmpView");
|
||||||
|
auto tmp_view_h = Kokkos::create_mirror_view(Kokkos::HostSpace(), tmpView);
|
||||||
|
if (case_number == 1) {
|
||||||
|
tmp_view_h(0) = 0;
|
||||||
|
tmp_view_h(1) = 0;
|
||||||
|
tmp_view_h(2) = 0;
|
||||||
|
tmp_view_h(3) = 2;
|
||||||
|
tmp_view_h(4) = 2;
|
||||||
|
tmp_view_h(5) = 1;
|
||||||
|
tmp_view_h(6) = 1;
|
||||||
|
tmp_view_h(7) = 1;
|
||||||
|
tmp_view_h(8) = 1;
|
||||||
|
tmp_view_h(9) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (case_number == 2) {
|
||||||
|
tmp_view_h(0) = 1;
|
||||||
|
tmp_view_h(1) = 2;
|
||||||
|
tmp_view_h(2) = 3;
|
||||||
|
tmp_view_h(3) = 4;
|
||||||
|
tmp_view_h(4) = 5;
|
||||||
|
tmp_view_h(5) = 6;
|
||||||
|
tmp_view_h(6) = 7;
|
||||||
|
tmp_view_h(7) = 8;
|
||||||
|
tmp_view_h(8) = 9;
|
||||||
|
tmp_view_h(9) = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (case_number == 3) {
|
||||||
|
tmp_view_h(0) = 8;
|
||||||
|
tmp_view_h(1) = 8;
|
||||||
|
tmp_view_h(2) = -1;
|
||||||
|
tmp_view_h(3) = -1;
|
||||||
|
tmp_view_h(4) = 5;
|
||||||
|
tmp_view_h(5) = 5;
|
||||||
|
tmp_view_h(6) = 5;
|
||||||
|
tmp_view_h(7) = 8;
|
||||||
|
tmp_view_h(8) = 2;
|
||||||
|
tmp_view_h(9) = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (case_number == 4) {
|
||||||
|
tmp_view_h(0) = 2;
|
||||||
|
tmp_view_h(1) = 2;
|
||||||
|
tmp_view_h(2) = 2;
|
||||||
|
tmp_view_h(3) = 2;
|
||||||
|
tmp_view_h(4) = 2;
|
||||||
|
tmp_view_h(5) = 2;
|
||||||
|
tmp_view_h(6) = 2;
|
||||||
|
tmp_view_h(7) = 2;
|
||||||
|
tmp_view_h(8) = 2;
|
||||||
|
tmp_view_h(9) = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (case_number == 5) {
|
||||||
|
tmp_view_h(0) = 1;
|
||||||
|
tmp_view_h(1) = 2;
|
||||||
|
tmp_view_h(2) = 3;
|
||||||
|
tmp_view_h(3) = 4;
|
||||||
|
tmp_view_h(4) = 5;
|
||||||
|
tmp_view_h(5) = 12;
|
||||||
|
tmp_view_h(6) = 5;
|
||||||
|
tmp_view_h(7) = 4;
|
||||||
|
tmp_view_h(8) = 3;
|
||||||
|
tmp_view_h(9) = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(tmpView, tmp_view_h);
|
||||||
|
copyInputViewToFixtureViews(tmpView);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::pair<int, value_type> goldSolutionMaxElement(int caseNumber) {
|
||||||
|
// returns {indexOfMaxElem, maxValue}
|
||||||
|
if (caseNumber == 1) {
|
||||||
|
return {3, 2};
|
||||||
|
} else if (caseNumber == 2) {
|
||||||
|
return {9, 10};
|
||||||
|
} else if (caseNumber == 3) {
|
||||||
|
return {0, 8};
|
||||||
|
} else if (caseNumber == 4) {
|
||||||
|
return {0, 2};
|
||||||
|
} else if (caseNumber == 5) {
|
||||||
|
return {5, 12};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::pair<int, value_type> goldSolutionMinElement(int caseNumber) {
|
||||||
|
// returns {indexOfMinElem, minValue}
|
||||||
|
if (caseNumber == 1) {
|
||||||
|
return {0, 0};
|
||||||
|
} else if (caseNumber == 2) {
|
||||||
|
return {0, 1};
|
||||||
|
} else if (caseNumber == 3) {
|
||||||
|
return {2, -1};
|
||||||
|
} else if (caseNumber == 4) {
|
||||||
|
return {0, 2};
|
||||||
|
} else if (caseNumber == 5) {
|
||||||
|
return {0, 1};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::pair<Kokkos::pair<int, value_type>, Kokkos::pair<int, value_type>>
|
||||||
|
goldSolutionMinMaxElement(int caseNumber) {
|
||||||
|
// returns {{indexOfMinElem, minValue}, {indexOfMaxElem, maxValue}}
|
||||||
|
// remember that for min it finds the first smallest element
|
||||||
|
// remember that for max it finds the last biggest element
|
||||||
|
if (caseNumber == 1) {
|
||||||
|
return {{0, 0}, {4, 2}};
|
||||||
|
} else if (caseNumber == 2) {
|
||||||
|
return {{0, 1}, {9, 10}};
|
||||||
|
} else if (caseNumber == 3) {
|
||||||
|
return {{2, -1}, {7, 8}};
|
||||||
|
} else if (caseNumber == 4) {
|
||||||
|
return {{0, 2}, {9, 2}};
|
||||||
|
} else if (caseNumber == 5) {
|
||||||
|
return {{0, 1}, {5, 12}};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_max_element_non_trivial_data(ViewType view);
|
||||||
|
template <class ViewType>
|
||||||
|
void test_min_element_non_trivial_data(ViewType view);
|
||||||
|
template <class ViewType>
|
||||||
|
void test_minmax_element_non_trivial_data(ViewType view);
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_max_element_non_trivial_data_custom_comp(ViewType view);
|
||||||
|
template <class ViewType>
|
||||||
|
void test_min_element_non_trivial_data_custom_comp(ViewType view);
|
||||||
|
template <class ViewType>
|
||||||
|
void test_minmax_element_non_trivial_data_custom_comp(ViewType view);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class IndexType, class ValueType, class ItType, class TestedViewType>
|
||||||
|
void std_algo_min_max_test_verify(Kokkos::pair<IndexType, ValueType> goldPair,
|
||||||
|
const ItType result,
|
||||||
|
TestedViewType testedView) {
|
||||||
|
// check that iterator is pointing to right element
|
||||||
|
EXPECT_EQ(result - KE::begin(testedView), goldPair.first);
|
||||||
|
|
||||||
|
// create a view for the result to copy into it the iterator's value
|
||||||
|
using result_view_t = Kokkos::View<int>;
|
||||||
|
result_view_t resultView("result");
|
||||||
|
CopyFromIteratorFunctor<ItType, result_view_t> cf(result, resultView);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy", 1, cf);
|
||||||
|
auto result_v_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), resultView);
|
||||||
|
|
||||||
|
// use the host mirror of the result view to check that the values match
|
||||||
|
EXPECT_EQ(result_v_h(), goldPair.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class GoldSolutionType, class ItType, class TestedViewType>
|
||||||
|
void std_algo_min_max_test_verify(const GoldSolutionType& goldSolution,
|
||||||
|
const ItType itMin, const ItType itMax,
|
||||||
|
TestedViewType testedView) {
|
||||||
|
std_algo_min_max_test_verify(goldSolution.first, itMin, testedView);
|
||||||
|
std_algo_min_max_test_verify(goldSolution.second, itMax, testedView);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_max_element_trivial_data(ViewType view) {
|
||||||
|
/* if we pass empty range, should return last */
|
||||||
|
auto result = KE::max_element(exespace(), KE::cbegin(view), KE::cbegin(view));
|
||||||
|
EXPECT_TRUE(result == KE::cbegin(view));
|
||||||
|
|
||||||
|
/* if we pass empty range, should return last */
|
||||||
|
auto it0 = KE::cbegin(view) + 3;
|
||||||
|
auto it1 = it0;
|
||||||
|
auto result2 = KE::max_element(exespace(), it0, it1);
|
||||||
|
EXPECT_TRUE(result2 == it1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_min_element_trivial_data(ViewType view) {
|
||||||
|
/* if we pass empty range, should return last */
|
||||||
|
auto result = KE::min_element(exespace(), KE::cbegin(view), KE::cbegin(view));
|
||||||
|
EXPECT_TRUE(result == KE::cbegin(view));
|
||||||
|
|
||||||
|
/* if we pass empty range, should return last */
|
||||||
|
auto it0 = KE::cbegin(view) + 3;
|
||||||
|
auto it1 = it0;
|
||||||
|
auto result2 = KE::min_element(exespace(), it0, it1);
|
||||||
|
EXPECT_TRUE(result2 == it1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_minmax_element_empty_range(ViewType view) {
|
||||||
|
auto result =
|
||||||
|
KE::minmax_element(exespace(), KE::cbegin(view), KE::cbegin(view));
|
||||||
|
EXPECT_TRUE(result.first == KE::cbegin(view));
|
||||||
|
EXPECT_TRUE(result.second == KE::cbegin(view));
|
||||||
|
auto it0 = KE::cbegin(view) + 3;
|
||||||
|
auto it1 = it0;
|
||||||
|
auto result2 = KE::minmax_element(exespace(), it0, it1);
|
||||||
|
EXPECT_TRUE(result2.first == it1);
|
||||||
|
EXPECT_TRUE(result2.second == it1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void std_algorithms_min_max_element_test::test_max_element_non_trivial_data(
|
||||||
|
ViewType view) {
|
||||||
|
for (int id = 1; id <= m_number_of_filling_cases; ++id) {
|
||||||
|
fillFixtureViews(id);
|
||||||
|
const auto gold_solution = goldSolutionMaxElement(id);
|
||||||
|
// API accepting view
|
||||||
|
{
|
||||||
|
const auto result = KE::max_element(exespace(), view);
|
||||||
|
std_algo_min_max_test_verify(gold_solution, result, view);
|
||||||
|
const auto result2 = KE::max_element("MYCUSTOMLABEL1", exespace(), view);
|
||||||
|
std_algo_min_max_test_verify(gold_solution, result2, view);
|
||||||
|
}
|
||||||
|
// API accepting iterators
|
||||||
|
{
|
||||||
|
const auto result =
|
||||||
|
KE::max_element(exespace(), KE::begin(view), KE::end(view));
|
||||||
|
std_algo_min_max_test_verify(gold_solution, result, view);
|
||||||
|
const auto result2 = KE::max_element("MYCUSTOMLABEL2", exespace(),
|
||||||
|
KE::begin(view), KE::end(view));
|
||||||
|
std_algo_min_max_test_verify(gold_solution, result2, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void std_algorithms_min_max_element_test::test_min_element_non_trivial_data(
|
||||||
|
ViewType view) {
|
||||||
|
for (int id = 1; id <= m_number_of_filling_cases; ++id) {
|
||||||
|
fillFixtureViews(id);
|
||||||
|
const auto goldPair = goldSolutionMinElement(id);
|
||||||
|
// API accepting view
|
||||||
|
{
|
||||||
|
const auto result = KE::min_element(exespace(), view);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result, view);
|
||||||
|
const auto result2 = KE::min_element("MYCUSTOMLABEL1", exespace(), view);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result2, view);
|
||||||
|
}
|
||||||
|
// API accepting iterators
|
||||||
|
{
|
||||||
|
const auto result =
|
||||||
|
KE::min_element(exespace(), KE::begin(view), KE::end(view));
|
||||||
|
std_algo_min_max_test_verify(goldPair, result, view);
|
||||||
|
const auto result2 = KE::min_element("MYCUSTOMLABEL2", exespace(),
|
||||||
|
KE::begin(view), KE::end(view));
|
||||||
|
std_algo_min_max_test_verify(goldPair, result2, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void std_algorithms_min_max_element_test::test_minmax_element_non_trivial_data(
|
||||||
|
ViewType view) {
|
||||||
|
for (int id = 1; id <= m_number_of_filling_cases; ++id) {
|
||||||
|
fillFixtureViews(id);
|
||||||
|
const auto gold = goldSolutionMinMaxElement(id);
|
||||||
|
{
|
||||||
|
auto result = KE::minmax_element(exespace(), view);
|
||||||
|
std_algo_min_max_test_verify(gold, result.first, result.second, view);
|
||||||
|
const auto result2 =
|
||||||
|
KE::minmax_element("MYCUSTOMLABEL1", exespace(), view);
|
||||||
|
std_algo_min_max_test_verify(gold, result2.first, result2.second, view);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto result =
|
||||||
|
KE::minmax_element(exespace(), KE::begin(view), KE::end(view));
|
||||||
|
std_algo_min_max_test_verify(gold, result.first, result.second, view);
|
||||||
|
const auto result2 = KE::minmax_element("MYCUSTOMLABEL2", exespace(),
|
||||||
|
KE::begin(view), KE::end(view));
|
||||||
|
std_algo_min_max_test_verify(gold, result2.first, result2.second, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
template <class ViewType>
|
||||||
|
void std_algorithms_min_max_element_test::
|
||||||
|
test_max_element_non_trivial_data_custom_comp(ViewType view) {
|
||||||
|
for (int id = 1; id <= m_number_of_filling_cases; ++id) {
|
||||||
|
fillFixtureViews(id);
|
||||||
|
const auto goldPair = goldSolutionMaxElement(id);
|
||||||
|
CustomLessThanComparator<value_type, value_type> comp;
|
||||||
|
// API accepting view
|
||||||
|
{
|
||||||
|
const auto result = KE::max_element(exespace(), view, comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result, view);
|
||||||
|
const auto result2 =
|
||||||
|
KE::max_element("MYCUSTOMLABEL3", exespace(), view, comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result2, view);
|
||||||
|
}
|
||||||
|
// API accepting iterators
|
||||||
|
{
|
||||||
|
const auto result =
|
||||||
|
KE::max_element(exespace(), KE::begin(view), KE::end(view), comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result, view);
|
||||||
|
const auto result2 = KE::max_element(
|
||||||
|
"MYCUSTOMLABEL4", exespace(), KE::begin(view), KE::end(view), comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result2, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void std_algorithms_min_max_element_test::
|
||||||
|
test_min_element_non_trivial_data_custom_comp(ViewType view) {
|
||||||
|
for (int id = 1; id <= m_number_of_filling_cases; ++id) {
|
||||||
|
fillFixtureViews(id);
|
||||||
|
const auto goldPair = goldSolutionMinElement(id);
|
||||||
|
CustomLessThanComparator<value_type, value_type> comp;
|
||||||
|
// API accepting view
|
||||||
|
{
|
||||||
|
const auto result = KE::min_element(exespace(), view, comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result, view);
|
||||||
|
const auto result2 =
|
||||||
|
KE::min_element("MYCUSTOMLABEL3", exespace(), view, comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result2, view);
|
||||||
|
}
|
||||||
|
// API accepting iterators
|
||||||
|
{
|
||||||
|
const auto result =
|
||||||
|
KE::min_element(exespace(), KE::begin(view), KE::end(view), comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result, view);
|
||||||
|
const auto result2 = KE::min_element(
|
||||||
|
"MYCUSTOMLABEL4", exespace(), KE::begin(view), KE::end(view), comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result2, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void std_algorithms_min_max_element_test::
|
||||||
|
test_minmax_element_non_trivial_data_custom_comp(ViewType view) {
|
||||||
|
for (int id = 1; id <= m_number_of_filling_cases; ++id) {
|
||||||
|
fillFixtureViews(id);
|
||||||
|
const auto goldPair = goldSolutionMinMaxElement(id);
|
||||||
|
CustomLessThanComparator<value_type, value_type> comp;
|
||||||
|
{
|
||||||
|
const auto result = KE::minmax_element(exespace(), view, comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result.first, result.second, view);
|
||||||
|
const auto result2 =
|
||||||
|
KE::minmax_element("MYCUSTOMLABEL3", exespace(), view, comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result2.first, result2.second,
|
||||||
|
view);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto result =
|
||||||
|
KE::minmax_element(exespace(), KE::begin(view), KE::end(view), comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result.first, result.second, view);
|
||||||
|
const auto result2 = KE::minmax_element(
|
||||||
|
"MYCUSTOMLABEL4", exespace(), KE::begin(view), KE::end(view), comp);
|
||||||
|
std_algo_min_max_test_verify(goldPair, result2.first, result2.second,
|
||||||
|
view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// trivial case
|
||||||
|
TEST_F(std_algorithms_min_max_element_test, min_element_empty_range) {
|
||||||
|
test_min_element_trivial_data(m_static_view);
|
||||||
|
test_min_element_trivial_data(m_dynamic_view);
|
||||||
|
test_min_element_trivial_data(m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_min_max_element_test, max_element_empty_range) {
|
||||||
|
test_max_element_trivial_data(m_static_view);
|
||||||
|
test_max_element_trivial_data(m_dynamic_view);
|
||||||
|
test_max_element_trivial_data(m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
// non-trivial data
|
||||||
|
TEST_F(std_algorithms_min_max_element_test, min_element_non_trivial_data) {
|
||||||
|
test_min_element_non_trivial_data(m_static_view);
|
||||||
|
test_min_element_non_trivial_data(m_dynamic_view);
|
||||||
|
test_min_element_non_trivial_data(m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_min_max_element_test, max_element_non_trivial_data) {
|
||||||
|
test_max_element_non_trivial_data(m_static_view);
|
||||||
|
test_max_element_non_trivial_data(m_dynamic_view);
|
||||||
|
test_max_element_non_trivial_data(m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
// non-trivial data, custom comp
|
||||||
|
TEST_F(std_algorithms_min_max_element_test,
|
||||||
|
min_element_non_trivial_data_custom_comp) {
|
||||||
|
test_min_element_non_trivial_data_custom_comp(m_static_view);
|
||||||
|
test_min_element_non_trivial_data_custom_comp(m_dynamic_view);
|
||||||
|
test_min_element_non_trivial_data_custom_comp(m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_min_max_element_test,
|
||||||
|
max_element_non_trivial_data_custom_comp) {
|
||||||
|
test_max_element_non_trivial_data_custom_comp(m_static_view);
|
||||||
|
test_max_element_non_trivial_data_custom_comp(m_dynamic_view);
|
||||||
|
test_max_element_non_trivial_data_custom_comp(m_strided_view);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(KOKKOS_ENABLE_OPENMPTARGET) && defined(KOKKOS_COMPILER_CLANG) && \
|
||||||
|
(KOKKOS_COMPILER_CLANG >= 1300)
|
||||||
|
TEST_F(std_algorithms_min_max_element_test, minmax_element_empty_range) {
|
||||||
|
test_minmax_element_empty_range(m_static_view);
|
||||||
|
test_minmax_element_empty_range(m_dynamic_view);
|
||||||
|
test_minmax_element_empty_range(m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_min_max_element_test, minmax_element_non_trivial_data) {
|
||||||
|
test_minmax_element_non_trivial_data(m_static_view);
|
||||||
|
test_minmax_element_non_trivial_data(m_dynamic_view);
|
||||||
|
test_minmax_element_non_trivial_data(m_strided_view);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
// OpenMPTarget does not yet support custom comparator
|
||||||
|
TEST_F(std_algorithms_min_max_element_test,
|
||||||
|
minmax_element_non_trivial_data_custom_comp) {
|
||||||
|
test_minmax_element_non_trivial_data_custom_comp(m_static_view);
|
||||||
|
test_minmax_element_non_trivial_data_custom_comp(m_dynamic_view);
|
||||||
|
test_minmax_element_non_trivial_data_custom_comp(m_strided_view);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
228
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsMismatch.cpp
Normal file
228
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsMismatch.cpp
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <iterator>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_NonModifyingSequenceOperations.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Mismatch {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(std::size_t ext1, std::size_t ext2,
|
||||||
|
const std::string& flag) {
|
||||||
|
std::cout << "mismatch: "
|
||||||
|
<< "ext1 = " << ext1 << ", "
|
||||||
|
<< "ext2 = " << ext2 << ", " << flag << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << ", "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ViewType, class... Args>
|
||||||
|
void run_single_scenario(ViewType view1, ViewType view2,
|
||||||
|
const std::string& flag, Args... args) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
|
||||||
|
const std::size_t ext1 = view1.extent(0);
|
||||||
|
const std::size_t ext2 = view2.extent(0);
|
||||||
|
// print_scenario_details<Tag, value_type>(ext1, ext2, flag);
|
||||||
|
|
||||||
|
aux_view_t aux_view1("aux_view1", ext1);
|
||||||
|
auto v1_h = create_mirror_view(Kokkos::HostSpace(), aux_view1);
|
||||||
|
aux_view_t aux_view2("aux_view2", ext2);
|
||||||
|
auto v2_h = create_mirror_view(Kokkos::HostSpace(), aux_view2);
|
||||||
|
|
||||||
|
// note that the checks ext1>0 and ext2>0 are there
|
||||||
|
// otherwise we get an error for CUDA NVCC DEBUG CI
|
||||||
|
|
||||||
|
// view is is always filled with 8's
|
||||||
|
if (ext1 > 0) {
|
||||||
|
for (std::size_t i = 0; i < ext1; ++i) {
|
||||||
|
v1_h(i) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == "fill-to-match") {
|
||||||
|
if (ext2 > 0) {
|
||||||
|
for (std::size_t i = 0; i < ext2; ++i) {
|
||||||
|
v2_h(i) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (flag == "fill-to-mismatch") {
|
||||||
|
// need to make them mismatch, so we fill
|
||||||
|
// with same value and only modifify the
|
||||||
|
// second view arbitrarily at middle point
|
||||||
|
|
||||||
|
if (ext2 > 0) {
|
||||||
|
for (std::size_t i = 0; i < ext2; ++i) {
|
||||||
|
v2_h(i) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make them mismatch at middle
|
||||||
|
v2_h(ext2 / 2) = -5;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Kokkos: stdalgo: test: mismatch: Invalid string");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view1, v1_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view1, view1);
|
||||||
|
Kokkos::parallel_for("copy1", view1.extent(0), F1);
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view2, v2_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F2(aux_view2, view2);
|
||||||
|
Kokkos::parallel_for("copy2", view2.extent(0), F2);
|
||||||
|
|
||||||
|
// run the std::mismatch on a host copy of the data
|
||||||
|
auto view1_h = create_host_space_copy(view1);
|
||||||
|
auto view2_h = create_host_space_copy(view2);
|
||||||
|
auto f1_h = KE::cbegin(view1_h);
|
||||||
|
auto l1_h = KE::cend(view1_h);
|
||||||
|
auto f2_h = KE::cbegin(view2_h);
|
||||||
|
auto l2_h = KE::cend(view2_h);
|
||||||
|
auto std_res = std::mismatch(f1_h, l1_h, f2_h, l2_h, args...);
|
||||||
|
const auto std_diff1 = std_res.first - f1_h;
|
||||||
|
const auto std_diff2 = std_res.second - f2_h;
|
||||||
|
|
||||||
|
{
|
||||||
|
// check our overloads with iterators
|
||||||
|
auto f1 = KE::cbegin(view1);
|
||||||
|
auto l1 = KE::cend(view1);
|
||||||
|
auto f2 = KE::cbegin(view2);
|
||||||
|
auto l2 = KE::cend(view2);
|
||||||
|
auto my_res1 = KE::mismatch(exespace(), f1, l1, f2, l2, args...);
|
||||||
|
auto my_res2 = KE::mismatch("label", exespace(), f1, l1, f2, l2, args...);
|
||||||
|
const auto my_diff11 = my_res1.first - f1;
|
||||||
|
const auto my_diff12 = my_res1.second - f2;
|
||||||
|
const auto my_diff21 = my_res2.first - f1;
|
||||||
|
const auto my_diff22 = my_res2.second - f2;
|
||||||
|
EXPECT_TRUE(my_diff11 == std_diff1);
|
||||||
|
EXPECT_TRUE(my_diff12 == std_diff2);
|
||||||
|
EXPECT_TRUE(my_diff21 == std_diff1);
|
||||||
|
EXPECT_TRUE(my_diff22 == std_diff2);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// check our overloads with views
|
||||||
|
auto my_res1 = KE::mismatch(exespace(), view1, view2, args...);
|
||||||
|
auto my_res2 = KE::mismatch("label", exespace(), view1, view2, args...);
|
||||||
|
const auto my_diff11 = my_res1.first - KE::begin(view1);
|
||||||
|
const auto my_diff12 = my_res1.second - KE::begin(view2);
|
||||||
|
const auto my_diff21 = my_res2.first - KE::begin(view1);
|
||||||
|
const auto my_diff22 = my_res2.second - KE::begin(view2);
|
||||||
|
EXPECT_TRUE(my_diff11 == std_diff1);
|
||||||
|
EXPECT_TRUE(my_diff12 == std_diff2);
|
||||||
|
EXPECT_TRUE(my_diff21 == std_diff1);
|
||||||
|
EXPECT_TRUE(my_diff22 == std_diff2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
using vecs_t = std::vector<std::string>;
|
||||||
|
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element", 1}, {"two-elements", 2},
|
||||||
|
{"small", 11}, {"medium", 21103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& scenario : scenarios) {
|
||||||
|
{
|
||||||
|
const std::size_t view1_ext = scenario.second;
|
||||||
|
auto view1 = create_view<ValueType>(Tag{}, view1_ext, "mismatch_view_1");
|
||||||
|
|
||||||
|
// for each view1 scenario, I want to test the case of a
|
||||||
|
// second view that is smaller, equal size and greater than the view1
|
||||||
|
const vecs_t view2cases = (scenario.first != "empty")
|
||||||
|
? vecs_t({"smaller", "equalsize", "larger"})
|
||||||
|
: vecs_t({"equalsize", "larger"});
|
||||||
|
|
||||||
|
for (auto it2 : view2cases) {
|
||||||
|
std::size_t view2_ext = view1_ext;
|
||||||
|
|
||||||
|
// modify extent of view2 based on what we want
|
||||||
|
if (std::string(it2) == "smaller") {
|
||||||
|
view2_ext -= 1;
|
||||||
|
} else if (std::string(it2) == "larger") {
|
||||||
|
view2_ext += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto view2 =
|
||||||
|
create_view<ValueType>(Tag{}, view2_ext, "mismatch_view_2");
|
||||||
|
|
||||||
|
// and now we want to test both the case view1 and view2 match,
|
||||||
|
// as well as the case where they don't match
|
||||||
|
for (const auto& it3 : {"fill-to-match", "fill-to-mismatch"}) {
|
||||||
|
// run to use default predicate
|
||||||
|
run_single_scenario<Tag>(view1, view2, it3);
|
||||||
|
|
||||||
|
// run using an arbitrary predicate
|
||||||
|
using predicate_type = IsEqualFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag>(view1, view2, it3, predicate_type());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mismatch_test, test) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Mismatch
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
209
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsModOps.cpp
Normal file
209
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsModOps.cpp
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingOperations.hpp>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace ModOps {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
// ------------
|
||||||
|
// move
|
||||||
|
// ------------
|
||||||
|
struct MyMovableType {
|
||||||
|
int m_value = 11;
|
||||||
|
|
||||||
|
MyMovableType() = default;
|
||||||
|
MyMovableType(MyMovableType&& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
m_value = other.m_value;
|
||||||
|
other.m_value = -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyMovableType& operator=(MyMovableType&& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
m_value = other.m_value;
|
||||||
|
other.m_value = -4;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_ops_test, move) {
|
||||||
|
MyMovableType a;
|
||||||
|
using move_t = decltype(KE::move(a));
|
||||||
|
static_assert(std::is_rvalue_reference<move_t>::value, "");
|
||||||
|
|
||||||
|
// move constr
|
||||||
|
MyMovableType b(KE::move(a));
|
||||||
|
EXPECT_TRUE(b.m_value == 11);
|
||||||
|
EXPECT_TRUE(a.m_value == -2);
|
||||||
|
|
||||||
|
// move assign
|
||||||
|
MyMovableType c;
|
||||||
|
c = KE::move(b);
|
||||||
|
EXPECT_TRUE(c.m_value == 11);
|
||||||
|
EXPECT_TRUE(b.m_value == -4);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
struct StdAlgoModSeqOpsTestMove {
|
||||||
|
ViewType m_view;
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(const int index) const {
|
||||||
|
typename ViewType::value_type a{11};
|
||||||
|
using move_t = decltype(KE::move(a));
|
||||||
|
static_assert(std::is_rvalue_reference<move_t>::value, "");
|
||||||
|
m_view(index) = KE::move(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
StdAlgoModSeqOpsTestMove(ViewType view) : m_view(view) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_ops_test, move_within_parfor) {
|
||||||
|
using view_t = Kokkos::View<double*>;
|
||||||
|
view_t a("a", 10);
|
||||||
|
|
||||||
|
StdAlgoModSeqOpsTestMove<view_t> fnc(a);
|
||||||
|
Kokkos::parallel_for(a.extent(0), fnc);
|
||||||
|
auto a_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), a);
|
||||||
|
for (std::size_t i = 0; i < a.extent(0); ++i) {
|
||||||
|
EXPECT_DOUBLE_EQ(a_h(0), 11.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------
|
||||||
|
// swap
|
||||||
|
// ------------
|
||||||
|
TEST(std_algorithms_mod_ops_test, swap) {
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
int b = 2;
|
||||||
|
KE::swap(a, b);
|
||||||
|
EXPECT_TRUE(a == 2);
|
||||||
|
EXPECT_TRUE(b == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
double a = 3.;
|
||||||
|
double b = 1.;
|
||||||
|
KE::swap(a, b);
|
||||||
|
EXPECT_DOUBLE_EQ(a, 1.);
|
||||||
|
EXPECT_DOUBLE_EQ(b, 3.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
struct StdAlgoModSeqOpsTestSwap {
|
||||||
|
ViewType m_view;
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(const int index) const {
|
||||||
|
typename ViewType::value_type newval{11};
|
||||||
|
KE::swap(m_view(index), newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
StdAlgoModSeqOpsTestSwap(ViewType aIn) : m_view(aIn) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_ops_test, swap_within_parfor) {
|
||||||
|
auto a = create_view<double>(stdalgos::DynamicTag{}, 10, "a");
|
||||||
|
StdAlgoModSeqOpsTestSwap<decltype(a)> fnc(a);
|
||||||
|
Kokkos::parallel_for(a.extent(0), fnc);
|
||||||
|
auto a_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), a);
|
||||||
|
for (std::size_t i = 0; i < a.extent(0); ++i) {
|
||||||
|
EXPECT_DOUBLE_EQ(a_h(0), 11.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------
|
||||||
|
// iter_swap
|
||||||
|
// ------------
|
||||||
|
template <class ViewType>
|
||||||
|
void test_iter_swap(ViewType view) {
|
||||||
|
/* fill view */
|
||||||
|
auto F = AssignIndexFunctor<ViewType>(view);
|
||||||
|
Kokkos::parallel_for(view.extent(0), std::move(F));
|
||||||
|
|
||||||
|
/* call iter_swap */
|
||||||
|
auto it1 = KE::begin(view);
|
||||||
|
KE::iter_swap(it1, it1 + 3);
|
||||||
|
KE::iter_swap(it1 + 4, it1 + 6);
|
||||||
|
|
||||||
|
/* check result */
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
auto a_dc = create_deep_copyable_compatible_clone(view);
|
||||||
|
auto a_h = create_mirror_view_and_copy(Kokkos::HostSpace(), a_dc);
|
||||||
|
EXPECT_TRUE(view.extent(0) == 10);
|
||||||
|
EXPECT_TRUE(a_h(0) == value_type(3));
|
||||||
|
EXPECT_TRUE(a_h(1) == value_type(1));
|
||||||
|
EXPECT_TRUE(a_h(2) == value_type(2));
|
||||||
|
EXPECT_TRUE(a_h(3) == value_type(0));
|
||||||
|
EXPECT_TRUE(a_h(4) == value_type(6));
|
||||||
|
EXPECT_TRUE(a_h(5) == value_type(5));
|
||||||
|
EXPECT_TRUE(a_h(6) == value_type(4));
|
||||||
|
EXPECT_TRUE(a_h(7) == value_type(7));
|
||||||
|
EXPECT_TRUE(a_h(8) == value_type(8));
|
||||||
|
EXPECT_TRUE(a_h(9) == value_type(9));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_ops_test, iter_swap_static_view) {
|
||||||
|
auto a = create_view<double>(stdalgos::DynamicTag{}, 10, "a");
|
||||||
|
test_iter_swap(a);
|
||||||
|
|
||||||
|
auto a1 = create_view<double>(stdalgos::StridedTwoTag{}, 10, "a1");
|
||||||
|
test_iter_swap(a1);
|
||||||
|
|
||||||
|
auto a2 = create_view<double>(stdalgos::StridedThreeTag{}, 10, "a2");
|
||||||
|
test_iter_swap(a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ModOps
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
429
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsModSeqOps.cpp
Normal file
429
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsModSeqOps.cpp
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include "std_algorithms/Kokkos_BeginEnd.hpp"
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
struct std_algorithms_mod_seq_ops_test : std_algorithms_test {
|
||||||
|
public:
|
||||||
|
virtual void SetUp() {
|
||||||
|
Kokkos::parallel_for(m_static_view.extent(0),
|
||||||
|
AssignIndexFunctor<static_view_t>(m_static_view));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, copy) {
|
||||||
|
auto result = KE::copy(exespace(), KE::begin(m_static_view),
|
||||||
|
KE::end(m_static_view), KE::begin(m_strided_view));
|
||||||
|
EXPECT_EQ(KE::end(m_strided_view), result);
|
||||||
|
compare_views(m_static_view, m_strided_view);
|
||||||
|
|
||||||
|
auto result2 = KE::copy(exespace(), KE::begin(m_strided_view),
|
||||||
|
KE::end(m_strided_view), KE::begin(m_dynamic_view));
|
||||||
|
EXPECT_EQ(KE::end(m_dynamic_view), result2);
|
||||||
|
compare_views(m_dynamic_view, m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, copy_view) {
|
||||||
|
EXPECT_EQ(KE::end(m_dynamic_view),
|
||||||
|
KE::copy(exespace(), m_static_view, m_dynamic_view));
|
||||||
|
compare_views(m_static_view, m_dynamic_view);
|
||||||
|
|
||||||
|
EXPECT_EQ(KE::end(m_strided_view),
|
||||||
|
KE::copy(exespace(), m_dynamic_view, m_strided_view));
|
||||||
|
compare_views(m_dynamic_view, m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, copy_n) {
|
||||||
|
constexpr std::size_t n = 5;
|
||||||
|
view_host_space_t expected("copy_n_expected");
|
||||||
|
expected(0) = 0;
|
||||||
|
expected(1) = 1;
|
||||||
|
expected(2) = 2;
|
||||||
|
expected(3) = 3;
|
||||||
|
expected(4) = 4;
|
||||||
|
expected(5) = 0;
|
||||||
|
expected(6) = 0;
|
||||||
|
expected(7) = 0;
|
||||||
|
expected(8) = 0;
|
||||||
|
expected(9) = 0;
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
auto first = KE::begin(m_static_view);
|
||||||
|
auto dest = KE::begin(m_dynamic_view);
|
||||||
|
EXPECT_EQ(dest + n, KE::copy_n(exespace(), first, n, dest));
|
||||||
|
compare_views(expected, m_dynamic_view);
|
||||||
|
|
||||||
|
// pass views
|
||||||
|
EXPECT_EQ(KE::begin(m_strided_view) + n,
|
||||||
|
KE::copy_n(exespace(), m_static_view, n, m_strided_view));
|
||||||
|
compare_views(expected, m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, copy_backward) {
|
||||||
|
auto first = KE::begin(m_static_view);
|
||||||
|
auto last = KE::end(m_static_view);
|
||||||
|
auto dest = KE::end(m_dynamic_view);
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
EXPECT_EQ(KE::begin(m_dynamic_view),
|
||||||
|
KE::copy_backward(exespace(), first, last, dest));
|
||||||
|
compare_views(m_static_view, m_dynamic_view);
|
||||||
|
|
||||||
|
// pass views
|
||||||
|
EXPECT_EQ(KE::begin(m_strided_view),
|
||||||
|
KE::copy_backward(exespace(), m_static_view, m_strided_view));
|
||||||
|
compare_views(m_static_view, m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, reverse_copy) {
|
||||||
|
view_host_space_t expected("reverse_copy_expected");
|
||||||
|
expected(0) = 9;
|
||||||
|
expected(1) = 8;
|
||||||
|
expected(2) = 7;
|
||||||
|
expected(3) = 6;
|
||||||
|
expected(4) = 5;
|
||||||
|
expected(5) = 4;
|
||||||
|
expected(6) = 3;
|
||||||
|
expected(7) = 2;
|
||||||
|
expected(8) = 1;
|
||||||
|
expected(9) = 0;
|
||||||
|
|
||||||
|
auto first = KE::begin(m_static_view);
|
||||||
|
auto last = KE::end(m_static_view);
|
||||||
|
auto dest = KE::begin(m_dynamic_view);
|
||||||
|
|
||||||
|
EXPECT_EQ(KE::end(m_dynamic_view),
|
||||||
|
KE::reverse_copy(exespace(), first, last, dest));
|
||||||
|
compare_views(expected, m_dynamic_view);
|
||||||
|
|
||||||
|
EXPECT_EQ(KE::end(m_strided_view),
|
||||||
|
KE::reverse_copy(exespace(), m_static_view, m_strided_view));
|
||||||
|
compare_views(expected, m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, fill) {
|
||||||
|
constexpr auto fill_value = 1.0;
|
||||||
|
view_host_space_t expected("fill_n_expected");
|
||||||
|
expected(0) = 0;
|
||||||
|
expected(1) = 0;
|
||||||
|
expected(2) = 0;
|
||||||
|
expected(3) = 0;
|
||||||
|
expected(4) = 0;
|
||||||
|
expected(5) = 0;
|
||||||
|
expected(6) = 0;
|
||||||
|
expected(7) = 0;
|
||||||
|
expected(8) = fill_value;
|
||||||
|
expected(9) = fill_value;
|
||||||
|
|
||||||
|
// pass iterators
|
||||||
|
KE::fill(exespace(), KE::begin(m_dynamic_view) + 8, KE::end(m_dynamic_view),
|
||||||
|
fill_value);
|
||||||
|
compare_views(expected, m_dynamic_view);
|
||||||
|
|
||||||
|
// pass view
|
||||||
|
KE::fill(exespace(), m_strided_view, fill_value);
|
||||||
|
verify_values(fill_value, m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, fill_n) {
|
||||||
|
constexpr auto fill_n_value = 100.0;
|
||||||
|
constexpr auto fill_n_new_value = 200.0;
|
||||||
|
|
||||||
|
// fill all elements
|
||||||
|
// pass iterator
|
||||||
|
EXPECT_EQ(KE::end(m_static_view),
|
||||||
|
KE::fill_n(exespace(), KE::begin(m_static_view),
|
||||||
|
m_static_view.extent(0), fill_n_value));
|
||||||
|
verify_values(fill_n_value, m_static_view);
|
||||||
|
|
||||||
|
// pass view
|
||||||
|
EXPECT_EQ(KE::end(m_strided_view),
|
||||||
|
KE::fill_n(exespace(), m_strided_view, m_strided_view.extent(0),
|
||||||
|
fill_n_value));
|
||||||
|
verify_values(fill_n_value, m_strided_view);
|
||||||
|
|
||||||
|
// fill zero elements
|
||||||
|
// pass view
|
||||||
|
EXPECT_EQ(KE::begin(m_dynamic_view),
|
||||||
|
KE::fill_n(exespace(), m_dynamic_view, 0, fill_n_new_value));
|
||||||
|
|
||||||
|
// fill single element
|
||||||
|
// pass iterator
|
||||||
|
EXPECT_EQ(
|
||||||
|
KE::begin(m_static_view) + 1,
|
||||||
|
KE::fill_n(exespace(), KE::begin(m_static_view), 1, fill_n_new_value));
|
||||||
|
|
||||||
|
view_host_space_t expected("fill_n_expected");
|
||||||
|
expected(0) = fill_n_new_value;
|
||||||
|
expected(1) = fill_n_value;
|
||||||
|
expected(2) = fill_n_value;
|
||||||
|
expected(3) = fill_n_value;
|
||||||
|
expected(4) = fill_n_value;
|
||||||
|
expected(5) = fill_n_value;
|
||||||
|
expected(6) = fill_n_value;
|
||||||
|
expected(7) = fill_n_value;
|
||||||
|
expected(8) = fill_n_value;
|
||||||
|
expected(9) = fill_n_value;
|
||||||
|
compare_views(expected, m_static_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TransformFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
value_type operator()(const value_type& val) const {
|
||||||
|
(void)val;
|
||||||
|
return static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, transform_from_fixture_unary_op) {
|
||||||
|
view_host_space_t gold_source("transform_expected");
|
||||||
|
gold_source(0) = 0;
|
||||||
|
gold_source(1) = 1;
|
||||||
|
gold_source(2) = 2;
|
||||||
|
gold_source(3) = 3;
|
||||||
|
gold_source(4) = 4;
|
||||||
|
gold_source(5) = 5;
|
||||||
|
gold_source(6) = 6;
|
||||||
|
gold_source(7) = 7;
|
||||||
|
gold_source(8) = 8;
|
||||||
|
gold_source(9) = 9;
|
||||||
|
|
||||||
|
// transform static view, store results in dynamic view
|
||||||
|
auto r1 = KE::transform(exespace(), KE::begin(m_static_view),
|
||||||
|
KE::end(m_static_view), KE::begin(m_dynamic_view),
|
||||||
|
TransformFunctor());
|
||||||
|
EXPECT_EQ(r1, KE::end(m_dynamic_view));
|
||||||
|
compare_views(gold_source, m_static_view);
|
||||||
|
verify_values(-1., m_dynamic_view);
|
||||||
|
|
||||||
|
// transform dynamic view, store results in strided view
|
||||||
|
auto r2 = KE::transform(exespace(), m_dynamic_view, m_strided_view,
|
||||||
|
TransformFunctor());
|
||||||
|
EXPECT_EQ(r2, KE::end(m_strided_view));
|
||||||
|
verify_values(-1., m_dynamic_view);
|
||||||
|
verify_values(-1., m_strided_view);
|
||||||
|
|
||||||
|
// transform strided view, store results in static view
|
||||||
|
auto r3 = KE::transform(exespace(), m_strided_view, m_static_view,
|
||||||
|
TransformFunctor());
|
||||||
|
EXPECT_EQ(r3, KE::end(m_static_view));
|
||||||
|
verify_values(-1., m_static_view);
|
||||||
|
verify_values(-1., m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TransformBinaryFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
value_type operator()(const value_type& val1, const value_type& val2) const {
|
||||||
|
return val1 + val2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, transform_from_fixture_binary_op) {
|
||||||
|
view_host_space_t expected("transform_expected");
|
||||||
|
expected(0) = 0;
|
||||||
|
expected(1) = 1;
|
||||||
|
expected(2) = 2;
|
||||||
|
expected(3) = 3;
|
||||||
|
expected(4) = 4;
|
||||||
|
expected(5) = 5;
|
||||||
|
expected(6) = 6;
|
||||||
|
expected(7) = 7;
|
||||||
|
expected(8) = 8;
|
||||||
|
expected(9) = 9;
|
||||||
|
|
||||||
|
auto r1 = KE::transform(exespace(), KE::begin(m_static_view),
|
||||||
|
KE::end(m_static_view), KE::begin(m_dynamic_view),
|
||||||
|
KE::begin(m_strided_view), TransformBinaryFunctor());
|
||||||
|
EXPECT_EQ(r1, KE::end(m_strided_view));
|
||||||
|
compare_views(expected, m_strided_view);
|
||||||
|
|
||||||
|
expected(0) = 0;
|
||||||
|
expected(1) = 2;
|
||||||
|
expected(2) = 4;
|
||||||
|
expected(3) = 6;
|
||||||
|
expected(4) = 8;
|
||||||
|
expected(5) = 10;
|
||||||
|
expected(6) = 12;
|
||||||
|
expected(7) = 14;
|
||||||
|
expected(8) = 16;
|
||||||
|
expected(9) = 18;
|
||||||
|
auto r2 = KE::transform("label", exespace(), m_static_view, m_strided_view,
|
||||||
|
m_dynamic_view, TransformBinaryFunctor());
|
||||||
|
EXPECT_EQ(r2, KE::end(m_dynamic_view));
|
||||||
|
compare_views(expected, m_dynamic_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr value_type generated_value = 2.0;
|
||||||
|
|
||||||
|
struct GenerateFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
value_type operator()() const { return generated_value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// cuda illegal instruction error appears for this one:
|
||||||
|
// constexpr int generate_f() { return generated_value; }
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, generate) {
|
||||||
|
// view + functor
|
||||||
|
KE::generate(exespace(), m_static_view, GenerateFunctor());
|
||||||
|
verify_values(generated_value, m_static_view);
|
||||||
|
|
||||||
|
// iterators + functor
|
||||||
|
KE::generate(exespace(), KE::begin(m_strided_view), KE::end(m_strided_view),
|
||||||
|
GenerateFunctor());
|
||||||
|
verify_values(generated_value, m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, generate_n) {
|
||||||
|
// iterator + functor
|
||||||
|
EXPECT_EQ(KE::end(m_static_view),
|
||||||
|
KE::generate_n(exespace(), KE::begin(m_static_view),
|
||||||
|
m_static_view.extent(0), GenerateFunctor()));
|
||||||
|
verify_values(generated_value, m_static_view);
|
||||||
|
|
||||||
|
// view + functor
|
||||||
|
EXPECT_EQ(KE::end(m_dynamic_view),
|
||||||
|
KE::generate_n(exespace(), m_dynamic_view, m_dynamic_view.extent(0),
|
||||||
|
GenerateFunctor()));
|
||||||
|
verify_values(generated_value, m_dynamic_view);
|
||||||
|
|
||||||
|
// view + functor, negative n
|
||||||
|
EXPECT_EQ(KE::begin(m_strided_view),
|
||||||
|
KE::generate_n(exespace(), m_strided_view, -1, GenerateFunctor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------
|
||||||
|
// test swap_ranges
|
||||||
|
// -----------------
|
||||||
|
template <class ViewType>
|
||||||
|
struct StdModOpsSwapRangesFillFunctorA {
|
||||||
|
ViewType m_view;
|
||||||
|
StdModOpsSwapRangesFillFunctorA(ViewType view) : m_view(view) {}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(int i) const { m_view(i) = i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
struct StdModOpsSwapRangesFillFunctorB {
|
||||||
|
ViewType m_view;
|
||||||
|
StdModOpsSwapRangesFillFunctorB(ViewType view) : m_view(view) {}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator()(int i) const { m_view(i) = 100 - i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void test_swap_ranges(ViewType view) {
|
||||||
|
const auto ext = view.extent(0);
|
||||||
|
|
||||||
|
/* fill view_a */
|
||||||
|
auto FA = StdModOpsSwapRangesFillFunctorA<ViewType>(view);
|
||||||
|
Kokkos::parallel_for(ext, std::move(FA));
|
||||||
|
|
||||||
|
/* fill view_b */
|
||||||
|
using static_view_type = std_algorithms_test::static_view_t;
|
||||||
|
static_view_type viewB("viewB");
|
||||||
|
auto FB = StdModOpsSwapRangesFillFunctorB<static_view_type>(viewB);
|
||||||
|
Kokkos::parallel_for(ext, std::move(FB));
|
||||||
|
|
||||||
|
/* call swap_ranges */
|
||||||
|
auto first1 = KE::begin(view) + 2;
|
||||||
|
auto last1 = first1 + 4;
|
||||||
|
auto first2 = KE::begin(viewB) + 1;
|
||||||
|
auto r = KE::swap_ranges(exespace(), first1, last1, first2);
|
||||||
|
EXPECT_EQ(r, first2 + 4);
|
||||||
|
|
||||||
|
/* check VIEW_A */
|
||||||
|
static_view_type checkViewA("tmp");
|
||||||
|
using cp_func_a_t = CopyFunctor<ViewType, static_view_type>;
|
||||||
|
parallel_for(ext, cp_func_a_t(view, checkViewA));
|
||||||
|
auto cvA_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), checkViewA);
|
||||||
|
EXPECT_TRUE(cvA_h(0) == 0);
|
||||||
|
EXPECT_TRUE(cvA_h(1) == 1);
|
||||||
|
EXPECT_TRUE(cvA_h(2) == 99);
|
||||||
|
EXPECT_TRUE(cvA_h(3) == 98);
|
||||||
|
EXPECT_TRUE(cvA_h(4) == 97);
|
||||||
|
EXPECT_TRUE(cvA_h(5) == 96);
|
||||||
|
EXPECT_TRUE(cvA_h(6) == 6);
|
||||||
|
EXPECT_TRUE(cvA_h(7) == 7);
|
||||||
|
EXPECT_TRUE(cvA_h(8) == 8);
|
||||||
|
EXPECT_TRUE(cvA_h(9) == 9);
|
||||||
|
|
||||||
|
/* check viewB */
|
||||||
|
static_view_type checkViewB("tmpB");
|
||||||
|
using cp_func_b_t = CopyFunctor<static_view_type, static_view_type>;
|
||||||
|
Kokkos::parallel_for(ext, cp_func_b_t(viewB, checkViewB));
|
||||||
|
auto cvB_h =
|
||||||
|
Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), checkViewB);
|
||||||
|
EXPECT_TRUE(cvB_h(0) == 100);
|
||||||
|
EXPECT_TRUE(cvB_h(1) == 2);
|
||||||
|
EXPECT_TRUE(cvB_h(2) == 3);
|
||||||
|
EXPECT_TRUE(cvB_h(3) == 4);
|
||||||
|
EXPECT_TRUE(cvB_h(4) == 5);
|
||||||
|
EXPECT_TRUE(cvB_h(5) == 95);
|
||||||
|
EXPECT_TRUE(cvB_h(6) == 94);
|
||||||
|
EXPECT_TRUE(cvB_h(7) == 93);
|
||||||
|
EXPECT_TRUE(cvB_h(8) == 92);
|
||||||
|
EXPECT_TRUE(cvB_h(9) == 91);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_mod_seq_ops_test, swap_ranges) {
|
||||||
|
test_swap_ranges(m_static_view);
|
||||||
|
test_swap_ranges(m_dynamic_view);
|
||||||
|
test_swap_ranges(m_strided_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
716
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsNumerics.cpp
Normal file
716
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsNumerics.cpp
Normal file
@ -0,0 +1,716 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_Numeric.hpp>
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
struct CustomValueType {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
CustomValueType(){};
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
CustomValueType(value_type val) : value(val){};
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
CustomValueType(const CustomValueType& other) { this->value = other.value; }
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
value_type& operator()() { return value; }
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
const value_type& operator()() const { return value; }
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
CustomValueType& operator+=(const CustomValueType& other) {
|
||||||
|
this->value += other.value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
CustomValueType& operator=(const CustomValueType& other) {
|
||||||
|
this->value = other.value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
CustomValueType operator+(const CustomValueType& other) const {
|
||||||
|
CustomValueType result;
|
||||||
|
result.value = this->value + other.value;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
CustomValueType operator*(const CustomValueType& other) const {
|
||||||
|
CustomValueType result;
|
||||||
|
result.value = this->value * other.value;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator==(const CustomValueType& other) const {
|
||||||
|
return this->value == other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// volatile overloads needed for the kokkos reductions
|
||||||
|
//
|
||||||
|
// note the void return
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator+=(const volatile CustomValueType& other) volatile {
|
||||||
|
this->value += other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note the void return
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
void operator=(const CustomValueType& other) volatile {
|
||||||
|
this->value = other.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
CustomValueType operator+(const volatile CustomValueType& other) const
|
||||||
|
volatile {
|
||||||
|
CustomValueType result;
|
||||||
|
result.value = this->value + other.value;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
value_type value = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TimesTwoUnaryTransformFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a) const { return (a * 2.); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct MultiplyAndHalveBinaryTransformFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return (a * b) * 0.5;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct SumJoinFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const volatile ValueType& a,
|
||||||
|
const volatile ValueType& b) const {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct std_algorithms_numerics_test : public ::testing::Test {
|
||||||
|
Kokkos::LayoutStride layout{20, 2};
|
||||||
|
|
||||||
|
// value_type
|
||||||
|
using static_view_t = Kokkos::View<value_type[20]>;
|
||||||
|
using dyn_view_t = Kokkos::View<value_type*>;
|
||||||
|
using strided_view_t = Kokkos::View<value_type*, Kokkos::LayoutStride>;
|
||||||
|
|
||||||
|
static_view_t m_static_view{"std-algo-test-1D-contiguous-view-static"};
|
||||||
|
dyn_view_t m_dynamic_view{"std-algo-test-1D-contiguous-view-dyn", 20};
|
||||||
|
strided_view_t m_strided_view{"std-algo-test-1D-strided-view", layout};
|
||||||
|
|
||||||
|
// custom scalar (cs)
|
||||||
|
using static_view_cs_t = Kokkos::View<CustomValueType[20]>;
|
||||||
|
using dyn_view_cs_t = Kokkos::View<CustomValueType*>;
|
||||||
|
using strided_view_cs_t =
|
||||||
|
Kokkos::View<CustomValueType*, Kokkos::LayoutStride>;
|
||||||
|
|
||||||
|
static_view_cs_t m_static_view_cs{
|
||||||
|
"std-algo-test-1D-contiguous-view-static-custom-scalar"};
|
||||||
|
dyn_view_cs_t m_dynamic_view_cs{
|
||||||
|
"std-algo-test-1D-contiguous-view-dyn-custom_scalar", 20};
|
||||||
|
strided_view_cs_t m_strided_view_cs{
|
||||||
|
"std-algo-test-1D-strided-view-custom-scalar", layout};
|
||||||
|
|
||||||
|
template <class ViewFromType, class ViewToType>
|
||||||
|
void copyPodViewToCustom(ViewFromType v_from, ViewToType v_to) {
|
||||||
|
for (std::size_t i = 0; i < v_from.extent(0); ++i) {
|
||||||
|
v_to(i)() = v_from(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillFixtureViews() {
|
||||||
|
static_view_t tmpView("tmpView");
|
||||||
|
static_view_cs_t tmpViewCs("tmpViewCs");
|
||||||
|
auto tmp_view_h = Kokkos::create_mirror_view(Kokkos::HostSpace(), tmpView);
|
||||||
|
auto tmp_view_cs_h =
|
||||||
|
Kokkos::create_mirror_view(Kokkos::HostSpace(), tmpViewCs);
|
||||||
|
tmp_view_h(0) = 0.;
|
||||||
|
tmp_view_h(1) = 0.;
|
||||||
|
tmp_view_h(2) = 0.;
|
||||||
|
tmp_view_h(3) = 2.;
|
||||||
|
tmp_view_h(4) = 2.;
|
||||||
|
tmp_view_h(5) = 1.;
|
||||||
|
tmp_view_h(6) = 1.;
|
||||||
|
tmp_view_h(7) = 1.;
|
||||||
|
tmp_view_h(8) = 1.;
|
||||||
|
tmp_view_h(9) = 0.;
|
||||||
|
tmp_view_h(10) = -2.;
|
||||||
|
tmp_view_h(11) = -2.;
|
||||||
|
tmp_view_h(12) = 0.;
|
||||||
|
tmp_view_h(13) = 2.;
|
||||||
|
tmp_view_h(14) = 2.;
|
||||||
|
tmp_view_h(15) = 1.;
|
||||||
|
tmp_view_h(16) = 1.;
|
||||||
|
tmp_view_h(17) = 1.;
|
||||||
|
tmp_view_h(18) = 1.;
|
||||||
|
tmp_view_h(19) = 0.;
|
||||||
|
|
||||||
|
copyPodViewToCustom(tmp_view_h, tmp_view_cs_h);
|
||||||
|
|
||||||
|
Kokkos::deep_copy(tmpView, tmp_view_h);
|
||||||
|
Kokkos::deep_copy(tmpViewCs, tmp_view_cs_h);
|
||||||
|
|
||||||
|
CopyFunctor<static_view_t, static_view_t> F1(tmpView, m_static_view);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy1", 20, F1);
|
||||||
|
|
||||||
|
CopyFunctor<static_view_t, dyn_view_t> F2(tmpView, m_dynamic_view);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy2", 20, F2);
|
||||||
|
|
||||||
|
CopyFunctor<static_view_t, strided_view_t> F3(tmpView, m_strided_view);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy3", 20, F3);
|
||||||
|
|
||||||
|
CopyFunctor<static_view_cs_t, static_view_cs_t> F4(tmpViewCs,
|
||||||
|
m_static_view_cs);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy4", 20, F4);
|
||||||
|
|
||||||
|
CopyFunctor<static_view_cs_t, dyn_view_cs_t> F5(tmpViewCs,
|
||||||
|
m_dynamic_view_cs);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy5", 20, F5);
|
||||||
|
|
||||||
|
CopyFunctor<static_view_cs_t, strided_view_cs_t> F6(tmpViewCs,
|
||||||
|
m_strided_view_cs);
|
||||||
|
Kokkos::parallel_for("_std_algo_copy6", 20, F6);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// test default case of transform_reduce
|
||||||
|
//
|
||||||
|
// test for both POD types and custom scalar types
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class ViewType1, class ViewType2,
|
||||||
|
class ValueType>
|
||||||
|
void run_and_check_transform_reduce_default(ViewType1 first_view,
|
||||||
|
ViewType2 second_view,
|
||||||
|
ValueType init_value,
|
||||||
|
ValueType result_value) {
|
||||||
|
// trivial cases
|
||||||
|
const auto r1 = KE::transform_reduce(ExecutionSpace(), KE::cbegin(first_view),
|
||||||
|
KE::cbegin(first_view),
|
||||||
|
KE::cbegin(second_view), init_value);
|
||||||
|
|
||||||
|
const auto r2 = KE::transform_reduce(
|
||||||
|
"MYLABEL", ExecutionSpace(), KE::cbegin(first_view),
|
||||||
|
KE::cbegin(first_view), KE::cbegin(second_view), init_value);
|
||||||
|
EXPECT_TRUE(r1 == init_value);
|
||||||
|
EXPECT_TRUE(r2 == init_value);
|
||||||
|
|
||||||
|
// non-trivial cases
|
||||||
|
const auto r3 = KE::transform_reduce(ExecutionSpace(), KE::cbegin(first_view),
|
||||||
|
KE::cend(first_view),
|
||||||
|
KE::cbegin(second_view), init_value);
|
||||||
|
|
||||||
|
const auto r4 = KE::transform_reduce(
|
||||||
|
"MYLABEL", ExecutionSpace(), KE::cbegin(first_view), KE::cend(first_view),
|
||||||
|
KE::cbegin(second_view), init_value);
|
||||||
|
|
||||||
|
const auto r5 = KE::transform_reduce(ExecutionSpace(), first_view,
|
||||||
|
second_view, init_value);
|
||||||
|
const auto r6 = KE::transform_reduce("MYLABEL", ExecutionSpace(), first_view,
|
||||||
|
second_view, init_value);
|
||||||
|
|
||||||
|
EXPECT_TRUE(r3 == result_value);
|
||||||
|
EXPECT_TRUE(r4 == result_value);
|
||||||
|
EXPECT_TRUE(r5 == result_value);
|
||||||
|
EXPECT_TRUE(r6 == result_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
transform_reduce_default_functors_using_pod_value_type) {
|
||||||
|
fillFixtureViews();
|
||||||
|
const value_type init0 = 0.;
|
||||||
|
const value_type init5 = 5.;
|
||||||
|
const value_type gold0 = 32.;
|
||||||
|
const value_type gold5 = 37.;
|
||||||
|
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_static_view, m_dynamic_view, init0, gold0);
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_static_view, m_dynamic_view, init5, gold5);
|
||||||
|
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_static_view, m_strided_view, init0, gold0);
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_static_view, m_strided_view, init5, gold5);
|
||||||
|
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_dynamic_view, m_strided_view, init0, gold0);
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_dynamic_view, m_strided_view, init5, gold5);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
transform_reduce_default_functors_using_custom_value_type) {
|
||||||
|
fillFixtureViews();
|
||||||
|
const CustomValueType init0{0.};
|
||||||
|
const CustomValueType init5{5.};
|
||||||
|
const CustomValueType gold0{32.};
|
||||||
|
const CustomValueType gold5{37.};
|
||||||
|
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_static_view_cs, m_dynamic_view_cs, init0, gold0);
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_static_view_cs, m_dynamic_view_cs, init5, gold5);
|
||||||
|
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_static_view_cs, m_strided_view_cs, init0, gold0);
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_static_view_cs, m_strided_view_cs, init5, gold5);
|
||||||
|
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_dynamic_view_cs, m_strided_view_cs, init0, gold0);
|
||||||
|
run_and_check_transform_reduce_default<exespace>(
|
||||||
|
m_dynamic_view_cs, m_strided_view_cs, init5, gold5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// transform_reduce for custom joiner and custom transform op
|
||||||
|
// test for both POD types and custom scalar types
|
||||||
|
//
|
||||||
|
// test overload1 accepting two intervals
|
||||||
|
//
|
||||||
|
// Note that in the std, the reducer is called BinaryReductionOp
|
||||||
|
// but in the Kokkos naming convention, it corresponds to a "joiner"
|
||||||
|
// that knows how to join two values.
|
||||||
|
// the "joiner" is assumed to be commutative:
|
||||||
|
//
|
||||||
|
// https://en.cppreference.com/w/cpp/algorithm/transform_reduce
|
||||||
|
//
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class ViewType1, class ViewType2,
|
||||||
|
class ValueType, class... Args>
|
||||||
|
void run_and_check_transform_reduce_overloadA(ViewType1 first_view,
|
||||||
|
ViewType2 second_view,
|
||||||
|
ValueType init_value,
|
||||||
|
ValueType result_value,
|
||||||
|
Args&&... args) {
|
||||||
|
// trivial cases
|
||||||
|
const auto r1 = KE::transform_reduce(
|
||||||
|
ExecutionSpace(), KE::cbegin(first_view), KE::cbegin(first_view),
|
||||||
|
KE::cbegin(second_view), init_value, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
const auto r2 =
|
||||||
|
KE::transform_reduce("MYLABEL", ExecutionSpace(), KE::cbegin(first_view),
|
||||||
|
KE::cbegin(first_view), KE::cbegin(second_view),
|
||||||
|
init_value, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
EXPECT_TRUE(r1 == init_value);
|
||||||
|
EXPECT_TRUE(r2 == init_value);
|
||||||
|
|
||||||
|
// non trivial cases
|
||||||
|
const auto r3 = KE::transform_reduce(
|
||||||
|
ExecutionSpace(), KE::cbegin(first_view), KE::cend(first_view),
|
||||||
|
KE::cbegin(second_view), init_value, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
const auto r4 = KE::transform_reduce(
|
||||||
|
"MYLABEL", ExecutionSpace(), KE::cbegin(first_view), KE::cend(first_view),
|
||||||
|
KE::cbegin(second_view), init_value, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
const auto r5 =
|
||||||
|
KE::transform_reduce(ExecutionSpace(), first_view, second_view,
|
||||||
|
init_value, std::forward<Args>(args)...);
|
||||||
|
const auto r6 =
|
||||||
|
KE::transform_reduce("MYLABEL", ExecutionSpace(), first_view, second_view,
|
||||||
|
init_value, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
EXPECT_TRUE(r3 == result_value);
|
||||||
|
EXPECT_TRUE(r4 == result_value);
|
||||||
|
EXPECT_TRUE(r5 == result_value);
|
||||||
|
EXPECT_TRUE(r6 == result_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
transform_reduce_custom_functors_overloadA_using_pod_value_type) {
|
||||||
|
using joiner_type = SumJoinFunctor<value_type>;
|
||||||
|
using transf_type = MultiplyAndHalveBinaryTransformFunctor<value_type>;
|
||||||
|
|
||||||
|
const value_type init0 = 0.;
|
||||||
|
const value_type init5 = 5.;
|
||||||
|
const value_type gold0 = 16.;
|
||||||
|
const value_type gold5 = 21.;
|
||||||
|
|
||||||
|
fillFixtureViews();
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_static_view, m_dynamic_view, init0, gold0, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_static_view, m_dynamic_view, init5, gold5, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_static_view, m_strided_view, init0, gold0, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_static_view, m_strided_view, init5, gold5, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_dynamic_view, m_strided_view, init0, gold0, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_dynamic_view, m_strided_view, init5, gold5, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
transform_reduce_custom_functors_overloadA_using_custom_value_type) {
|
||||||
|
using joiner_type = SumJoinFunctor<CustomValueType>;
|
||||||
|
using transf_type = MultiplyAndHalveBinaryTransformFunctor<CustomValueType>;
|
||||||
|
|
||||||
|
const CustomValueType init0{0.};
|
||||||
|
const CustomValueType init5{5.};
|
||||||
|
const CustomValueType gold0{16.};
|
||||||
|
const CustomValueType gold5{21.};
|
||||||
|
|
||||||
|
fillFixtureViews();
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_static_view_cs, m_dynamic_view_cs, init0, gold0, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_static_view_cs, m_dynamic_view_cs, init5, gold5, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_static_view_cs, m_strided_view_cs, init0, gold0, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_static_view_cs, m_strided_view_cs, init5, gold5, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_dynamic_view_cs, m_strided_view_cs, init0, gold0, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadA<exespace>(
|
||||||
|
m_dynamic_view_cs, m_strided_view_cs, init5, gold5, joiner_type(),
|
||||||
|
transf_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// transform_reduce for custom joiner and custom transform op
|
||||||
|
// test for both POD types and custom scalar types
|
||||||
|
//
|
||||||
|
// test overload1 accepting single interval/view
|
||||||
|
//
|
||||||
|
// Note that in the std, the reducer is called BinaryReductionOp
|
||||||
|
// but in the Kokkos naming convention, it corresponds to a "joiner"
|
||||||
|
// that knows how to join two values.
|
||||||
|
// the "joiner" is assumed to be commutative:
|
||||||
|
//
|
||||||
|
// https://en.cppreference.com/w/cpp/algorithm/transform_reduce
|
||||||
|
//
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class ViewType, class ValueType, class... Args>
|
||||||
|
void run_and_check_transform_reduce_overloadB(ViewType view,
|
||||||
|
ValueType init_value,
|
||||||
|
ValueType result_value,
|
||||||
|
Args&&... args) {
|
||||||
|
// trivial
|
||||||
|
const auto r1 =
|
||||||
|
KE::transform_reduce(ExecutionSpace(), KE::cbegin(view), KE::cbegin(view),
|
||||||
|
init_value, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
const auto r2 = KE::transform_reduce("MYLABEL", ExecutionSpace(),
|
||||||
|
KE::cbegin(view), KE::cbegin(view),
|
||||||
|
init_value, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
EXPECT_TRUE(r1 == init_value);
|
||||||
|
EXPECT_TRUE(r2 == init_value);
|
||||||
|
|
||||||
|
// non trivial
|
||||||
|
const auto r3 =
|
||||||
|
KE::transform_reduce(ExecutionSpace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
init_value, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
const auto r4 = KE::transform_reduce("MYLABEL", ExecutionSpace(),
|
||||||
|
KE::cbegin(view), KE::cend(view),
|
||||||
|
init_value, std::forward<Args>(args)...);
|
||||||
|
const auto r5 = KE::transform_reduce(ExecutionSpace(), view, init_value,
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
const auto r6 = KE::transform_reduce("MYLABEL", ExecutionSpace(), view,
|
||||||
|
init_value, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
EXPECT_TRUE(r3 == result_value);
|
||||||
|
EXPECT_TRUE(r4 == result_value);
|
||||||
|
EXPECT_TRUE(r5 == result_value);
|
||||||
|
EXPECT_TRUE(r6 == result_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
transform_reduce_custom_functors_overloadB_using_pod_value_type) {
|
||||||
|
using joiner_type = SumJoinFunctor<value_type>;
|
||||||
|
using transf_type = TimesTwoUnaryTransformFunctor<value_type>;
|
||||||
|
|
||||||
|
const value_type init0 = 0.;
|
||||||
|
const value_type init5 = 5.;
|
||||||
|
const value_type gold0 = 24.;
|
||||||
|
const value_type gold5 = 29.;
|
||||||
|
|
||||||
|
fillFixtureViews();
|
||||||
|
run_and_check_transform_reduce_overloadB<exespace>(
|
||||||
|
m_static_view, init0, gold0, joiner_type(), transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadB<exespace>(
|
||||||
|
m_dynamic_view, init5, gold5, joiner_type(), transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadB<exespace>(
|
||||||
|
m_strided_view, init0, gold0, joiner_type(), transf_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
transform_reduce_custom_functors_overloadB_using_custom_value_type) {
|
||||||
|
using joiner_type = SumJoinFunctor<CustomValueType>;
|
||||||
|
using transf_type = TimesTwoUnaryTransformFunctor<CustomValueType>;
|
||||||
|
|
||||||
|
const CustomValueType init0{0.};
|
||||||
|
const CustomValueType init5{5.};
|
||||||
|
const CustomValueType gold0{24.};
|
||||||
|
const CustomValueType gold5{29.};
|
||||||
|
|
||||||
|
fillFixtureViews();
|
||||||
|
run_and_check_transform_reduce_overloadB<exespace>(
|
||||||
|
m_static_view_cs, init0, gold0, joiner_type(), transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadB<exespace>(
|
||||||
|
m_dynamic_view_cs, init5, gold5, joiner_type(), transf_type());
|
||||||
|
run_and_check_transform_reduce_overloadB<exespace>(
|
||||||
|
m_strided_view_cs, init0, gold0, joiner_type(), transf_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// test reduce overload1
|
||||||
|
//
|
||||||
|
// test for both POD types and custom scalar types
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class ViewType, class ValueType>
|
||||||
|
void run_and_check_reduce_overloadA(ViewType view, ValueType non_trivial_result,
|
||||||
|
ValueType trivial_result) {
|
||||||
|
// trivial cases
|
||||||
|
const auto r1 =
|
||||||
|
KE::reduce(ExecutionSpace(), KE::cbegin(view), KE::cbegin(view));
|
||||||
|
const auto r2 = KE::reduce("MYLABEL", ExecutionSpace(), KE::cbegin(view),
|
||||||
|
KE::cbegin(view));
|
||||||
|
EXPECT_TRUE(r1 == trivial_result);
|
||||||
|
EXPECT_TRUE(r2 == trivial_result);
|
||||||
|
|
||||||
|
// non trivial cases
|
||||||
|
const auto r3 =
|
||||||
|
KE::reduce(ExecutionSpace(), KE::cbegin(view), KE::cend(view));
|
||||||
|
const auto r4 =
|
||||||
|
KE::reduce("MYLABEL", ExecutionSpace(), KE::cbegin(view), KE::cend(view));
|
||||||
|
const auto r5 = KE::reduce(ExecutionSpace(), view);
|
||||||
|
const auto r6 = KE::reduce("MYLABEL", ExecutionSpace(), view);
|
||||||
|
|
||||||
|
EXPECT_TRUE(r3 == non_trivial_result);
|
||||||
|
EXPECT_TRUE(r4 == non_trivial_result);
|
||||||
|
EXPECT_TRUE(r5 == non_trivial_result);
|
||||||
|
EXPECT_TRUE(r6 == non_trivial_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
reduce_default_functors_overloadA_using_pod_value_type) {
|
||||||
|
fillFixtureViews();
|
||||||
|
const value_type trivial_gold = 0.;
|
||||||
|
const value_type non_trivial_gold = 12.;
|
||||||
|
run_and_check_reduce_overloadA<exespace>(m_static_view, non_trivial_gold,
|
||||||
|
trivial_gold);
|
||||||
|
run_and_check_reduce_overloadA<exespace>(m_dynamic_view, non_trivial_gold,
|
||||||
|
trivial_gold);
|
||||||
|
run_and_check_reduce_overloadA<exespace>(m_strided_view, non_trivial_gold,
|
||||||
|
trivial_gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
reduce_default_functors_overloadA_using_custom_value_type) {
|
||||||
|
fillFixtureViews();
|
||||||
|
const CustomValueType trivial_gold{0.};
|
||||||
|
const CustomValueType non_trivial_gold{12.};
|
||||||
|
run_and_check_reduce_overloadA<exespace>(m_static_view_cs, non_trivial_gold,
|
||||||
|
trivial_gold);
|
||||||
|
run_and_check_reduce_overloadA<exespace>(m_dynamic_view_cs, non_trivial_gold,
|
||||||
|
trivial_gold);
|
||||||
|
run_and_check_reduce_overloadA<exespace>(m_strided_view_cs, non_trivial_gold,
|
||||||
|
trivial_gold);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// test reduce overload2 with init value
|
||||||
|
//
|
||||||
|
// test for both POD types and custom scalar types
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class ViewType, class ValueType>
|
||||||
|
void run_and_check_reduce_overloadB(ViewType view, ValueType result_value,
|
||||||
|
ValueType init_value) {
|
||||||
|
// trivial cases
|
||||||
|
const auto r1 = KE::reduce(ExecutionSpace(), KE::cbegin(view),
|
||||||
|
KE::cbegin(view), init_value);
|
||||||
|
const auto r2 = KE::reduce("MYLABEL", ExecutionSpace(), KE::cbegin(view),
|
||||||
|
KE::cbegin(view), init_value);
|
||||||
|
EXPECT_TRUE(r1 == init_value);
|
||||||
|
EXPECT_TRUE(r2 == init_value);
|
||||||
|
|
||||||
|
// non trivial cases
|
||||||
|
const auto r3 = KE::reduce(ExecutionSpace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
init_value);
|
||||||
|
const auto r4 = KE::reduce("MYLABEL", ExecutionSpace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), init_value);
|
||||||
|
const auto r5 = KE::reduce(ExecutionSpace(), view, init_value);
|
||||||
|
const auto r6 = KE::reduce("MYLABEL", ExecutionSpace(), view, init_value);
|
||||||
|
|
||||||
|
EXPECT_TRUE(r3 == result_value);
|
||||||
|
EXPECT_TRUE(r4 == result_value);
|
||||||
|
EXPECT_TRUE(r5 == result_value);
|
||||||
|
EXPECT_TRUE(r6 == result_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
reduce_default_functors_overloadB_using_pod_value_type) {
|
||||||
|
fillFixtureViews();
|
||||||
|
const value_type init = 5.;
|
||||||
|
const value_type gold = 17.;
|
||||||
|
run_and_check_reduce_overloadB<exespace>(m_static_view, gold, init);
|
||||||
|
run_and_check_reduce_overloadB<exespace>(m_dynamic_view, gold, init);
|
||||||
|
run_and_check_reduce_overloadB<exespace>(m_strided_view, gold, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
reduce_default_functors_overloadB_using_custom_value_type) {
|
||||||
|
fillFixtureViews();
|
||||||
|
const CustomValueType init{5.};
|
||||||
|
const CustomValueType gold{17.};
|
||||||
|
run_and_check_reduce_overloadB<exespace>(m_static_view_cs, gold, init);
|
||||||
|
run_and_check_reduce_overloadB<exespace>(m_dynamic_view_cs, gold, init);
|
||||||
|
run_and_check_reduce_overloadB<exespace>(m_strided_view_cs, gold, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// test reduce overload3 with init value
|
||||||
|
//
|
||||||
|
// test for both POD types and custom scalar types
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
template <class ExecutionSpace, class ViewType, class ValueType, class BinaryOp>
|
||||||
|
void run_and_check_reduce_overloadC(ViewType view, ValueType result_value,
|
||||||
|
ValueType init_value, BinaryOp joiner) {
|
||||||
|
// trivial cases
|
||||||
|
const auto r1 = KE::reduce(ExecutionSpace(), KE::cbegin(view),
|
||||||
|
KE::cbegin(view), init_value, joiner);
|
||||||
|
const auto r2 = KE::reduce("MYLABEL", ExecutionSpace(), KE::cbegin(view),
|
||||||
|
KE::cbegin(view), init_value, joiner);
|
||||||
|
EXPECT_TRUE(r1 == init_value);
|
||||||
|
EXPECT_TRUE(r2 == init_value);
|
||||||
|
|
||||||
|
// non trivial cases
|
||||||
|
const auto r3 = KE::reduce(ExecutionSpace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
init_value, joiner);
|
||||||
|
const auto r4 = KE::reduce("MYLABEL", ExecutionSpace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), init_value, joiner);
|
||||||
|
const auto r5 = KE::reduce(ExecutionSpace(), view, init_value, joiner);
|
||||||
|
const auto r6 =
|
||||||
|
KE::reduce("MYLABEL", ExecutionSpace(), view, init_value, joiner);
|
||||||
|
|
||||||
|
EXPECT_TRUE(r3 == result_value);
|
||||||
|
EXPECT_TRUE(r4 == result_value);
|
||||||
|
EXPECT_TRUE(r5 == result_value);
|
||||||
|
EXPECT_TRUE(r6 == result_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
reduce_custom_functors_using_pod_value_type) {
|
||||||
|
using joiner_type = SumJoinFunctor<value_type>;
|
||||||
|
|
||||||
|
fillFixtureViews();
|
||||||
|
const value_type init = 5.;
|
||||||
|
const value_type gold = 17.;
|
||||||
|
run_and_check_reduce_overloadC<exespace>(m_static_view, gold, init,
|
||||||
|
joiner_type());
|
||||||
|
run_and_check_reduce_overloadC<exespace>(m_dynamic_view, gold, init,
|
||||||
|
joiner_type());
|
||||||
|
run_and_check_reduce_overloadC<exespace>(m_strided_view, gold, init,
|
||||||
|
joiner_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_numerics_test,
|
||||||
|
reduce_custom_functors_using_custom_value_type) {
|
||||||
|
using joiner_type = SumJoinFunctor<CustomValueType>;
|
||||||
|
|
||||||
|
fillFixtureViews();
|
||||||
|
const CustomValueType init{5.};
|
||||||
|
const CustomValueType gold{17.};
|
||||||
|
run_and_check_reduce_overloadC<exespace>(m_static_view_cs, gold, init,
|
||||||
|
joiner_type());
|
||||||
|
run_and_check_reduce_overloadC<exespace>(m_dynamic_view_cs, gold, init,
|
||||||
|
joiner_type());
|
||||||
|
run_and_check_reduce_overloadC<exespace>(m_strided_view_cs, gold, init,
|
||||||
|
joiner_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,303 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_PartitioningOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace PartitionCopy {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-100, 100) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = value_type{-5} + static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(22);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-c") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(-13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeFrom, class ResultType, class ViewTypeDestTrue,
|
||||||
|
class ViewTypeDestFalse, class PredType>
|
||||||
|
void verify_data(const std::string& name, ResultType my_result,
|
||||||
|
ViewTypeFrom view_from, ViewTypeDestTrue view_dest_true,
|
||||||
|
ViewTypeDestFalse view_dest_false, PredType pred) {
|
||||||
|
using value_type = typename ViewTypeFrom::value_type;
|
||||||
|
static_assert(
|
||||||
|
std::is_same<value_type, typename ViewTypeDestTrue::value_type>::value,
|
||||||
|
"");
|
||||||
|
static_assert(
|
||||||
|
std::is_same<value_type, typename ViewTypeDestFalse::value_type>::value,
|
||||||
|
"");
|
||||||
|
|
||||||
|
const std::size_t ext = view_from.extent(0);
|
||||||
|
|
||||||
|
// create host clone of view_from and run std::partition_copy on it
|
||||||
|
auto view_from_h = create_host_space_copy(view_from);
|
||||||
|
std::vector<value_type> std_vec_true(ext, 0);
|
||||||
|
std::vector<value_type> std_vec_false(ext, 0);
|
||||||
|
auto std_result =
|
||||||
|
std::partition_copy(KE::cbegin(view_from_h), KE::cend(view_from_h),
|
||||||
|
std_vec_true.begin(), std_vec_false.begin(), pred);
|
||||||
|
const std::size_t std_diff_true = std_result.first - std_vec_true.begin();
|
||||||
|
const std::size_t std_diff_false = std_result.second - std_vec_false.begin();
|
||||||
|
const std::size_t my_diff_true = my_result.first - KE::begin(view_dest_true);
|
||||||
|
const std::size_t my_diff_false =
|
||||||
|
my_result.second - KE::begin(view_dest_false);
|
||||||
|
EXPECT_TRUE(std_diff_true == my_diff_true);
|
||||||
|
EXPECT_TRUE(std_diff_false == my_diff_false);
|
||||||
|
|
||||||
|
auto view_dest_true_h = create_host_space_copy(view_dest_true);
|
||||||
|
for (std::size_t i = 0; i < std_diff_true; ++i) {
|
||||||
|
EXPECT_TRUE(std_vec_true[i] == view_dest_true_h(i));
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << " std_true = " << std_vec_true[i] << " "
|
||||||
|
// << " mine = " << view_dest_true_h(i) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
auto view_dest_false_h = create_host_space_copy(view_dest_false);
|
||||||
|
for (std::size_t i = 0; i < std_diff_false; ++i) {
|
||||||
|
EXPECT_TRUE(std_vec_false[i] == view_dest_false_h(i));
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << " std_false = " << std_vec_false[i] << " "
|
||||||
|
// << " mine = " << view_dest_false_h(i) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
EXPECT_TRUE(my_diff_true == 0);
|
||||||
|
EXPECT_TRUE(my_diff_false == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
EXPECT_TRUE(my_diff_true == 0);
|
||||||
|
EXPECT_TRUE(my_diff_false == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
EXPECT_TRUE(my_diff_true == 1);
|
||||||
|
EXPECT_TRUE(my_diff_false == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
EXPECT_TRUE(my_diff_true == 1);
|
||||||
|
EXPECT_TRUE(my_diff_false == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
EXPECT_TRUE(my_diff_true == 1);
|
||||||
|
EXPECT_TRUE(my_diff_false == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
EXPECT_TRUE(my_diff_true == 13);
|
||||||
|
EXPECT_TRUE(my_diff_false == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-c") {
|
||||||
|
EXPECT_TRUE(my_diff_true == 0);
|
||||||
|
EXPECT_TRUE(my_diff_false == 15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "partition_copy: " << name << ", " <<
|
||||||
|
// view_tag_to_string(Tag{})
|
||||||
|
// << ", " << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "partition_copy_from");
|
||||||
|
IsEvenFunctor<ValueType> pred;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest_true =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "partition_copy_dest_true");
|
||||||
|
auto view_dest_false =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "partition_copy_dest_false");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto result = KE::partition_copy(
|
||||||
|
exespace(), KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest_true), KE::begin(view_dest_false), pred);
|
||||||
|
verify_data(name, result, view_from, view_dest_true, view_dest_false, pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest_true =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "partition_copy_dest_true");
|
||||||
|
auto view_dest_false =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "partition_copy_dest_false");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto result = KE::partition_copy(
|
||||||
|
"my_label", exespace(), KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest_true), KE::begin(view_dest_false), pred);
|
||||||
|
verify_data(name, result, view_from, view_dest_true, view_dest_false, pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest_true =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "partition_copy_dest_true");
|
||||||
|
auto view_dest_false =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "partition_copy_dest_false");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto result = KE::partition_copy(exespace(), view_from, view_dest_true,
|
||||||
|
view_dest_false, pred);
|
||||||
|
verify_data(name, result, view_from, view_dest_true, view_dest_false, pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest_true =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "partition_copy_dest_true");
|
||||||
|
auto view_dest_false =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "partition_copy_dest_false");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto result = KE::partition_copy("my_label", exespace(), view_from,
|
||||||
|
view_dest_true, view_dest_false, pred);
|
||||||
|
verify_data(name, result, view_from, view_dest_true, view_dest_false, pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1},
|
||||||
|
{"one-element-b", 1}, {"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"small-c", 15},
|
||||||
|
{"medium", 103}}; // {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_partitioning_ops, partition_copy) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace PartitionCopy
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_PartitioningOperations.hpp>
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
struct std_algorithms_partitioning_test : public std_algorithms_test {
|
||||||
|
enum FixtureViews {
|
||||||
|
Mixed,
|
||||||
|
NegativeFirst,
|
||||||
|
AllNegative,
|
||||||
|
AllPositive,
|
||||||
|
NegativeLast,
|
||||||
|
SingleNegative,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
void fillFixtureViews(FixtureViews caseNumber) {
|
||||||
|
static_view_t tmpView("tmpView");
|
||||||
|
auto tmp_view_h = Kokkos::create_mirror_view(Kokkos::HostSpace(), tmpView);
|
||||||
|
|
||||||
|
switch (caseNumber) {
|
||||||
|
case FixtureViews::Mixed:
|
||||||
|
tmp_view_h(0) = -1;
|
||||||
|
tmp_view_h(1) = -2;
|
||||||
|
tmp_view_h(2) = 3;
|
||||||
|
tmp_view_h(3) = -4;
|
||||||
|
tmp_view_h(4) = 5;
|
||||||
|
tmp_view_h(5) = -6;
|
||||||
|
tmp_view_h(6) = 7;
|
||||||
|
tmp_view_h(7) = -8;
|
||||||
|
tmp_view_h(8) = 9;
|
||||||
|
tmp_view_h(9) = 10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FixtureViews::NegativeFirst:
|
||||||
|
tmp_view_h(0) = -2;
|
||||||
|
tmp_view_h(1) = -4;
|
||||||
|
tmp_view_h(2) = -6;
|
||||||
|
tmp_view_h(3) = -80;
|
||||||
|
tmp_view_h(4) = 5;
|
||||||
|
tmp_view_h(5) = 7;
|
||||||
|
tmp_view_h(6) = 115;
|
||||||
|
tmp_view_h(7) = 3;
|
||||||
|
tmp_view_h(8) = 9;
|
||||||
|
tmp_view_h(9) = 11;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FixtureViews::AllNegative:
|
||||||
|
tmp_view_h(0) = -2;
|
||||||
|
tmp_view_h(1) = -4;
|
||||||
|
tmp_view_h(2) = -6;
|
||||||
|
tmp_view_h(3) = -8;
|
||||||
|
tmp_view_h(4) = -4;
|
||||||
|
tmp_view_h(5) = -12;
|
||||||
|
tmp_view_h(6) = -14;
|
||||||
|
tmp_view_h(7) = -2;
|
||||||
|
tmp_view_h(8) = -6;
|
||||||
|
tmp_view_h(9) = -8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FixtureViews::AllPositive:
|
||||||
|
tmp_view_h(0) = 11;
|
||||||
|
tmp_view_h(1) = 3;
|
||||||
|
tmp_view_h(2) = 17;
|
||||||
|
tmp_view_h(3) = 9;
|
||||||
|
tmp_view_h(4) = 3;
|
||||||
|
tmp_view_h(5) = 11;
|
||||||
|
tmp_view_h(6) = 13;
|
||||||
|
tmp_view_h(7) = 1;
|
||||||
|
tmp_view_h(8) = 9;
|
||||||
|
tmp_view_h(9) = 43;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FixtureViews::NegativeLast:
|
||||||
|
tmp_view_h(0) = 1;
|
||||||
|
tmp_view_h(1) = 11;
|
||||||
|
tmp_view_h(2) = 1;
|
||||||
|
tmp_view_h(3) = 33;
|
||||||
|
tmp_view_h(4) = 3;
|
||||||
|
tmp_view_h(5) = 3;
|
||||||
|
tmp_view_h(6) = -3;
|
||||||
|
tmp_view_h(7) = -5;
|
||||||
|
tmp_view_h(8) = -5;
|
||||||
|
tmp_view_h(9) = -10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FixtureViews::SingleNegative:
|
||||||
|
tmp_view_h(0) = -200;
|
||||||
|
tmp_view_h(1) = 1;
|
||||||
|
tmp_view_h(2) = 1;
|
||||||
|
tmp_view_h(3) = 3;
|
||||||
|
tmp_view_h(4) = 3;
|
||||||
|
tmp_view_h(5) = 211;
|
||||||
|
tmp_view_h(6) = 3;
|
||||||
|
tmp_view_h(7) = 5;
|
||||||
|
tmp_view_h(8) = 5;
|
||||||
|
tmp_view_h(9) = 11;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(tmpView, tmp_view_h);
|
||||||
|
copyInputViewToFixtureViews(tmpView);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool goldSolutionIsPartitioned(FixtureViews caseNumber) const {
|
||||||
|
switch (caseNumber) {
|
||||||
|
case Mixed: return false;
|
||||||
|
case NegativeFirst: return true;
|
||||||
|
case AllNegative: return true;
|
||||||
|
case AllPositive: return false;
|
||||||
|
case NegativeLast: return false;
|
||||||
|
case SingleNegative: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int goldSolutionPartitionedPoint(FixtureViews caseNumber) const {
|
||||||
|
switch (caseNumber) {
|
||||||
|
case Mixed: return 2;
|
||||||
|
case NegativeFirst: return 4;
|
||||||
|
case AllNegative: return 10;
|
||||||
|
case AllPositive: return 0;
|
||||||
|
case NegativeLast: return 0;
|
||||||
|
case SingleNegative: return 1;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_partitioning_test, is_partitioned_trivial) {
|
||||||
|
IsNegativeFunctor<value_type> p;
|
||||||
|
const auto result1 = KE::is_partitioned(exespace(), KE::cbegin(m_static_view),
|
||||||
|
KE::cbegin(m_static_view), p);
|
||||||
|
EXPECT_EQ(true, result1);
|
||||||
|
|
||||||
|
const auto result2 = KE::is_partitioned(
|
||||||
|
exespace(), KE::cbegin(m_dynamic_view), KE::cbegin(m_dynamic_view), p);
|
||||||
|
EXPECT_EQ(true, result2);
|
||||||
|
|
||||||
|
const auto result3 = KE::is_partitioned(
|
||||||
|
exespace(), KE::cbegin(m_strided_view), KE::cbegin(m_strided_view), p);
|
||||||
|
EXPECT_EQ(true, result3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_partitioning_test, is_partitioned_accepting_iterators) {
|
||||||
|
const IsNegativeFunctor<value_type> p;
|
||||||
|
|
||||||
|
for (int id = 0; id < FixtureViews::Count; ++id) {
|
||||||
|
fillFixtureViews(static_cast<FixtureViews>(id));
|
||||||
|
const bool goldBool =
|
||||||
|
goldSolutionIsPartitioned(static_cast<FixtureViews>(id));
|
||||||
|
const auto result1 = KE::is_partitioned(
|
||||||
|
exespace(), KE::cbegin(m_static_view), KE::cend(m_static_view), p);
|
||||||
|
EXPECT_EQ(goldBool, result1);
|
||||||
|
|
||||||
|
const auto result2 = KE::is_partitioned(
|
||||||
|
exespace(), KE::cbegin(m_dynamic_view), KE::cend(m_dynamic_view), p);
|
||||||
|
EXPECT_EQ(goldBool, result2);
|
||||||
|
|
||||||
|
const auto result3 = KE::is_partitioned(
|
||||||
|
exespace(), KE::cbegin(m_strided_view), KE::cend(m_strided_view), p);
|
||||||
|
EXPECT_EQ(goldBool, result3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_partitioning_test, is_partitioned_accepting_view) {
|
||||||
|
const IsNegativeFunctor<value_type> p;
|
||||||
|
|
||||||
|
for (int id = 0; id < FixtureViews::Count; ++id) {
|
||||||
|
fillFixtureViews(static_cast<FixtureViews>(id));
|
||||||
|
const bool goldBool =
|
||||||
|
goldSolutionIsPartitioned(static_cast<FixtureViews>(id));
|
||||||
|
const auto result1 = KE::is_partitioned(exespace(), m_static_view, p);
|
||||||
|
EXPECT_EQ(goldBool, result1);
|
||||||
|
|
||||||
|
const auto result2 = KE::is_partitioned(exespace(), m_dynamic_view, p);
|
||||||
|
EXPECT_EQ(goldBool, result2);
|
||||||
|
|
||||||
|
const auto result3 = KE::is_partitioned(exespace(), m_strided_view, p);
|
||||||
|
EXPECT_EQ(goldBool, result3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(std_algorithms_partitioning_test, partition_point) {
|
||||||
|
const IsNegativeFunctor<value_type> p;
|
||||||
|
|
||||||
|
for (int id = 0; id < FixtureViews::Count; ++id) {
|
||||||
|
fillFixtureViews(static_cast<FixtureViews>(id));
|
||||||
|
const auto goldIndex =
|
||||||
|
goldSolutionPartitionedPoint(static_cast<FixtureViews>(id));
|
||||||
|
auto first1 = KE::cbegin(m_static_view);
|
||||||
|
auto last1 = KE::cend(m_static_view);
|
||||||
|
const auto result1 = KE::partition_point(exespace(), first1, last1, p);
|
||||||
|
EXPECT_EQ(goldIndex, result1 - first1);
|
||||||
|
|
||||||
|
auto first2 = KE::cbegin(m_dynamic_view);
|
||||||
|
auto last2 = KE::cend(m_dynamic_view);
|
||||||
|
const auto result2 = KE::partition_point(exespace(), first2, last2, p);
|
||||||
|
EXPECT_EQ(goldIndex, result2 - first2);
|
||||||
|
|
||||||
|
auto first3 = KE::cbegin(m_strided_view);
|
||||||
|
auto last3 = KE::cend(m_strided_view);
|
||||||
|
const auto result3 = KE::partition_point(exespace(), first3, last3, p);
|
||||||
|
EXPECT_EQ(goldIndex, result3 - first3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
234
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRemove.cpp
Normal file
234
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRemove.cpp
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Remove {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
constexpr int match_value = 4;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-100, 100) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(match_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(match_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(match_value);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(match_value);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(-12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 8 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(match_value);
|
||||||
|
} else {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeData, class ViewTypeTest, class MyItResult>
|
||||||
|
void verify_data(ViewTypeData view_data_h, ViewTypeTest view_test,
|
||||||
|
MyItResult my_result) {
|
||||||
|
// run std::remove
|
||||||
|
auto std_result =
|
||||||
|
std::remove(KE::begin(view_data_h), KE::end(view_data_h), match_value);
|
||||||
|
|
||||||
|
// check that returned iterators are correct
|
||||||
|
const std::size_t std_diff = std_result - KE::begin(view_data_h);
|
||||||
|
const std::size_t my_diff = my_result - KE::begin(view_test);
|
||||||
|
EXPECT_TRUE(std_diff == my_diff);
|
||||||
|
|
||||||
|
// check the actual data after algo has been applied
|
||||||
|
auto view_test_h = create_host_space_copy(view_test);
|
||||||
|
for (std::size_t i = 0; i < my_diff; ++i) {
|
||||||
|
EXPECT_TRUE(view_test_h(i) == view_data_h[i]);
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << "mine: " << view_test_h(i) << " "
|
||||||
|
// << "std: " << view_data_h(i)
|
||||||
|
// << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "remove: " << name << ", " << view_tag_to_string(Tag{}) << ",
|
||||||
|
// "
|
||||||
|
// << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "remove_from");
|
||||||
|
fill_view(view, name);
|
||||||
|
// make host copy BEFORE running algo
|
||||||
|
auto data_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::remove(exespace(), KE::begin(view), KE::end(view),
|
||||||
|
(ValueType)match_value);
|
||||||
|
verify_data(data_h, view, rit);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "remove_from");
|
||||||
|
fill_view(view, name);
|
||||||
|
// make host copy BEFORE running algo
|
||||||
|
auto data_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::remove("label", exespace(), KE::begin(view), KE::end(view),
|
||||||
|
(ValueType)match_value);
|
||||||
|
verify_data(data_h, view, rit);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "remove_from");
|
||||||
|
fill_view(view, name);
|
||||||
|
// make host copy BEFORE running algo
|
||||||
|
auto data_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::remove(exespace(), view, (ValueType)match_value);
|
||||||
|
verify_data(data_h, view, rit);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "remove_from");
|
||||||
|
fill_view(view, name);
|
||||||
|
// make host copy BEFORE running algo
|
||||||
|
auto data_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::remove("label", exespace(), view, (ValueType)match_value);
|
||||||
|
verify_data(data_h, view, rit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 13031}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, remove) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Remove
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
265
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRemoveCopy.cpp
Normal file
265
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRemoveCopy.cpp
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace RemoveCopy {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
constexpr int match_value = 4;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-100, 100) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-100., 100.) { m_gen.seed(341043); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(match_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(match_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(match_value);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(match_value);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(-12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 8 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(match_value);
|
||||||
|
} else {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewFromType, class ViewDestType, class MyItResult>
|
||||||
|
void verify_data(ViewFromType view_from, ViewDestType view_dest,
|
||||||
|
MyItResult my_result) {
|
||||||
|
// make a host copy of the view_from
|
||||||
|
auto view_from_h = create_host_space_copy(view_from);
|
||||||
|
const std::size_t ext = view_from_h.extent(0);
|
||||||
|
using value_type = typename ViewFromType::value_type;
|
||||||
|
|
||||||
|
// run std::remove_copy
|
||||||
|
std::vector<value_type> gold_dest_std(ext);
|
||||||
|
auto std_result =
|
||||||
|
std::remove_copy(KE::cbegin(view_from_h), KE::cend(view_from_h),
|
||||||
|
gold_dest_std.begin(), (value_type)match_value);
|
||||||
|
|
||||||
|
// check that returned iterators are correct
|
||||||
|
const std::size_t std_diff = std_result - gold_dest_std.begin();
|
||||||
|
const std::size_t my_diff = my_result - KE::begin(view_dest);
|
||||||
|
EXPECT_TRUE(std_diff == my_diff);
|
||||||
|
|
||||||
|
// check the actual data after algo has been applied
|
||||||
|
auto view_dest_h = create_host_space_copy(view_dest);
|
||||||
|
for (std::size_t i = 0; i < my_diff; ++i) {
|
||||||
|
EXPECT_TRUE(view_dest_h(i) == gold_dest_std[i]);
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << "mine: " << view_dest_h(i) << " "
|
||||||
|
// << "std: " << gold_dest_std[i]
|
||||||
|
// << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "remove_copy: " << name << ", " << view_tag_to_string(Tag{})
|
||||||
|
// << ", " << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_view_from");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_view_dest");
|
||||||
|
auto rit =
|
||||||
|
KE::remove_copy(exespace(), KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), (ValueType)match_value);
|
||||||
|
verify_data(view_from, view_dest, rit);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_view_from");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_view_dest");
|
||||||
|
auto rit = KE::remove_copy("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
(ValueType)match_value);
|
||||||
|
verify_data(view_from, view_dest, rit);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_view_from");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_view_dest");
|
||||||
|
auto rit = KE::remove_copy(exespace(), view_from, view_dest,
|
||||||
|
(ValueType)match_value);
|
||||||
|
verify_data(view_from, view_dest, rit);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_view_from");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_view_dest");
|
||||||
|
auto rit = KE::remove_copy("label", exespace(), view_from, view_dest,
|
||||||
|
(ValueType)match_value);
|
||||||
|
verify_data(view_from, view_dest, rit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 13031}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, remove_copy) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace RemoveCopy
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace RemoveCopyIf {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-100, 100) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(22);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(-12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeFrom, class ViewTypeDest, class MyItResult,
|
||||||
|
class PredicateType>
|
||||||
|
void verify_data(ViewTypeFrom view_from, ViewTypeDest view_dest,
|
||||||
|
MyItResult my_result, PredicateType pred) {
|
||||||
|
// make a host copy of the view_from
|
||||||
|
auto view_from_h = create_host_space_copy(view_from);
|
||||||
|
const std::size_t ext = view_from_h.extent(0);
|
||||||
|
using value_type = typename ViewTypeFrom::value_type;
|
||||||
|
|
||||||
|
// run std::remove_copy_if
|
||||||
|
std::vector<value_type> gold_dest_std(ext);
|
||||||
|
auto std_result =
|
||||||
|
std::remove_copy_if(KE::cbegin(view_from_h), KE::cend(view_from_h),
|
||||||
|
gold_dest_std.begin(), pred);
|
||||||
|
|
||||||
|
// check that returned iterators are correct
|
||||||
|
const std::size_t std_diff = std_result - gold_dest_std.begin();
|
||||||
|
const std::size_t my_diff = my_result - KE::begin(view_dest);
|
||||||
|
EXPECT_TRUE(std_diff == my_diff);
|
||||||
|
|
||||||
|
// check the actual data after algo has been applied
|
||||||
|
auto view_dest_h = create_host_space_copy(view_dest);
|
||||||
|
for (std::size_t i = 0; i < my_diff; ++i) {
|
||||||
|
EXPECT_TRUE(view_dest_h(i) == gold_dest_std[i]);
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << "mine: " << view_dest_h(i) << " "
|
||||||
|
// << "std: " << gold_dest_std[i]
|
||||||
|
// << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "remove_copy_if: " << name << ", " <<
|
||||||
|
// view_tag_to_string(Tag{})
|
||||||
|
// << ", " << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
using pred_type = IsEvenFunctor<ValueType>;
|
||||||
|
pred_type remove_if_even;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_if_view_from");
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_if_view_dest");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto rit = KE::remove_copy_if(exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
remove_if_even);
|
||||||
|
verify_data(view_from, view_dest, rit, remove_if_even);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_if_view_from");
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_if_view_dest");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto rit = KE::remove_copy_if("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
remove_if_even);
|
||||||
|
verify_data(view_from, view_dest, rit, remove_if_even);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_if_view_from");
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_if_view_dest");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto rit =
|
||||||
|
KE::remove_copy_if(exespace(), view_from, view_dest, remove_if_even);
|
||||||
|
verify_data(view_from, view_dest, rit, remove_if_even);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_if_view_from");
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "remove_copy_if_view_dest");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto rit = KE::remove_copy_if("label", exespace(), view_from, view_dest,
|
||||||
|
remove_if_even);
|
||||||
|
verify_data(view_from, view_dest, rit, remove_if_even);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 23103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, remove_copy_if) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace RemoveCopyIf
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
231
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRemoveIf.cpp
Normal file
231
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRemoveIf.cpp
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace RemoveIf {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-100, 100) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(22);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(-12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeData, class ViewTypeTest, class MyItResult,
|
||||||
|
class PredicateType>
|
||||||
|
void verify_data(ViewTypeData view_data_h, ViewTypeTest view_test,
|
||||||
|
MyItResult my_result, PredicateType pred) {
|
||||||
|
// run std::remove_if
|
||||||
|
auto std_result =
|
||||||
|
std::remove_if(KE::begin(view_data_h), KE::end(view_data_h), pred);
|
||||||
|
|
||||||
|
// check that returned iterators are correct
|
||||||
|
const std::size_t std_diff = std_result - KE::begin(view_data_h);
|
||||||
|
const std::size_t my_diff = my_result - KE::begin(view_test);
|
||||||
|
EXPECT_TRUE(std_diff == my_diff);
|
||||||
|
|
||||||
|
// check the actual data after algo has been applied
|
||||||
|
auto view_test_h = create_host_space_copy(view_test);
|
||||||
|
for (std::size_t i = 0; i < my_diff; ++i) {
|
||||||
|
EXPECT_TRUE(view_test_h(i) == view_data_h[i]);
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << "mine: " << view_test_h(i) << " "
|
||||||
|
// << "std: " << view_data_h(i)
|
||||||
|
// << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "remove_if: " << name << ", " << view_tag_to_string(Tag{})
|
||||||
|
// << ", " << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
using pred_type = IsEvenFunctor<ValueType>;
|
||||||
|
pred_type remove_if_even;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "remove_if_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// make host copy BEFORE running algo
|
||||||
|
auto data_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::remove_if(exespace(), KE::begin(view), KE::end(view),
|
||||||
|
remove_if_even);
|
||||||
|
verify_data(data_h, view, rit, remove_if_even);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "remove_if_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// make host copy BEFORE running algo
|
||||||
|
auto data_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::remove_if("label", exespace(), KE::begin(view),
|
||||||
|
KE::end(view), remove_if_even);
|
||||||
|
verify_data(data_h, view, rit, remove_if_even);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "remove_if_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// make host copy BEFORE running algo
|
||||||
|
auto data_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::remove_if(exespace(), view, remove_if_even);
|
||||||
|
verify_data(data_h, view, rit, remove_if_even);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "remove_if_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// make host copy BEFORE running algo
|
||||||
|
auto data_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::remove_if("label", exespace(), view, remove_if_even);
|
||||||
|
verify_data(data_h, view, rit, remove_if_even);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 23103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, remove_if) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace RemoveIf
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
255
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsReplace.cpp
Normal file
255
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsReplace.cpp
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Replace {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = value_type{-5} + static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(5) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i < 4) {
|
||||||
|
v_h(i) = static_cast<value_type>(-1);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(-1);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ValueType>
|
||||||
|
void verify_data(const std::string& name, ViewType1 test_view,
|
||||||
|
ValueType new_value) {
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
auto view_dc = create_deep_copyable_compatible_clone(test_view);
|
||||||
|
auto view_h = create_mirror_view_and_copy(Kokkos::HostSpace(), view_dc);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
EXPECT_TRUE(view_h(0) == ValueType{1});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
EXPECT_TRUE(view_h(0) == new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
EXPECT_TRUE(view_h(0) == ValueType{1});
|
||||||
|
EXPECT_TRUE(view_h(1) == new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
EXPECT_TRUE(view_h(0) == new_value);
|
||||||
|
EXPECT_TRUE(view_h(1) == ValueType{-1});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < view_h.extent(0); ++i) {
|
||||||
|
if (i == 0 || i == 3 || i == 5 || i == 6) {
|
||||||
|
EXPECT_TRUE(view_h(i) == new_value);
|
||||||
|
} else {
|
||||||
|
const auto gold = ValueType{-5} + static_cast<ValueType>(i + 1);
|
||||||
|
EXPECT_TRUE(view_h(i) == gold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < view_h.extent(0); ++i) {
|
||||||
|
if (i < 4) {
|
||||||
|
EXPECT_TRUE(view_h(i) == ValueType{-1});
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(view_h(i) == new_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < view_h.extent(0); ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
EXPECT_TRUE(view_h(i) == ValueType{-1});
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(view_h(i) == new_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "replace: " << name << ", " << view_tag_to_string(Tag{}) << ",
|
||||||
|
// "
|
||||||
|
// << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
ValueType old_value{2};
|
||||||
|
ValueType new_value{43};
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "replace");
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(view, name);
|
||||||
|
KE::replace(exespace(), KE::begin(view), KE::end(view), old_value,
|
||||||
|
new_value);
|
||||||
|
verify_data(name, view, new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(view, name);
|
||||||
|
KE::replace("label", exespace(), KE::begin(view), KE::end(view), old_value,
|
||||||
|
new_value);
|
||||||
|
verify_data(name, view, new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(view, name);
|
||||||
|
KE::replace(exespace(), view, old_value, new_value);
|
||||||
|
verify_data(name, view, new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(view, name);
|
||||||
|
KE::replace("label", exespace(), view, old_value, new_value);
|
||||||
|
verify_data(name, view, new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 1103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_replace_ops_test, replace) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Replace
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace ReplaceCopy {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = value_type{-5} + static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(5) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i < 4) {
|
||||||
|
v_h(i) = static_cast<value_type>(-1);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(-1);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeFrom, class ViewTypeTest, class ValueType>
|
||||||
|
void verify_data(const std::string& name, ViewTypeFrom view_from,
|
||||||
|
ViewTypeTest view_test, ValueType new_value) {
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
auto view_test_dc = create_deep_copyable_compatible_clone(view_test);
|
||||||
|
auto view_test_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_test_dc);
|
||||||
|
|
||||||
|
auto view_from_dc = create_deep_copyable_compatible_clone(view_from);
|
||||||
|
auto view_from_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_from_dc);
|
||||||
|
|
||||||
|
// we check that view_from is unchanged from what it was after filling
|
||||||
|
// while view_test should be changed
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
EXPECT_TRUE(view_from_h(0) == ValueType{1});
|
||||||
|
EXPECT_TRUE(view_test_h(0) == view_from_h(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
EXPECT_TRUE(view_from_h(0) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_test_h(0) == new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
EXPECT_TRUE(view_from_h(0) == ValueType{1});
|
||||||
|
EXPECT_TRUE(view_from_h(1) == ValueType{2});
|
||||||
|
|
||||||
|
EXPECT_TRUE(view_test_h(0) == view_from_h(0));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
EXPECT_TRUE(view_from_h(0) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_from_h(1) == ValueType{-1});
|
||||||
|
|
||||||
|
EXPECT_TRUE(view_test_h(0) == new_value);
|
||||||
|
EXPECT_TRUE(view_test_h(1) == view_from_h(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < view_test_h.extent(0); ++i) {
|
||||||
|
if (i == 0 || i == 3 || i == 5 || i == 6) {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == new_value);
|
||||||
|
} else {
|
||||||
|
const auto gold = ValueType{-5} + static_cast<ValueType>(i + 1);
|
||||||
|
EXPECT_TRUE(view_from_h(i) == gold);
|
||||||
|
EXPECT_TRUE(view_test_h(i) == gold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < view_test_h.extent(0); ++i) {
|
||||||
|
if (i < 4) {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{-1});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == view_from_h(i));
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == new_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < view_test_h.extent(0); ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{-1});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == view_from_h(i));
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == new_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "replace_copy: " << name << ", " << view_tag_to_string(Tag{})
|
||||||
|
// << ", " << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
ValueType old_value{2};
|
||||||
|
ValueType new_value{43};
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_from");
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_dest");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto rit =
|
||||||
|
KE::replace_copy(exespace(), KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), old_value, new_value);
|
||||||
|
verify_data(name, view_from, view_dest, new_value);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_from");
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_dest");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto rit = KE::replace_copy("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
old_value, new_value);
|
||||||
|
verify_data(name, view_from, view_dest, new_value);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_from");
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_dest");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto rit = KE::replace_copy(exespace(), view_from, view_dest, old_value,
|
||||||
|
new_value);
|
||||||
|
verify_data(name, view_from, view_dest, new_value);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_from");
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_dest");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto rit = KE::replace_copy("label", exespace(), view_from, view_dest,
|
||||||
|
old_value, new_value);
|
||||||
|
verify_data(name, view_from, view_dest, new_value);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 1103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_replace_ops_test, replace_copy) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ReplaceCopy
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,300 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace ReplaceCopyIf {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = value_type{-5} + static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(5) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i < 4) {
|
||||||
|
v_h(i) = static_cast<value_type>(-1);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
v_h(i) = static_cast<value_type>(-1);
|
||||||
|
} else {
|
||||||
|
v_h(i) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeFrom, class ViewTypeTest, class ValueType>
|
||||||
|
void verify_data(const std::string& name, ViewTypeFrom view_from,
|
||||||
|
ViewTypeTest view_test, ValueType new_value) {
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
auto view_test_dc = create_deep_copyable_compatible_clone(view_test);
|
||||||
|
auto view_test_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_test_dc);
|
||||||
|
|
||||||
|
auto view_from_dc = create_deep_copyable_compatible_clone(view_from);
|
||||||
|
auto view_from_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_from_dc);
|
||||||
|
|
||||||
|
// we check that view_from is unchanged from what it was after filling
|
||||||
|
// while view_test should be changed
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
EXPECT_TRUE(view_from_h(0) == ValueType{1});
|
||||||
|
EXPECT_TRUE(view_test_h(0) == view_from_h(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
EXPECT_TRUE(view_from_h(0) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_test_h(0) == new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
EXPECT_TRUE(view_from_h(0) == ValueType{1});
|
||||||
|
EXPECT_TRUE(view_from_h(1) == ValueType{2});
|
||||||
|
|
||||||
|
EXPECT_TRUE(view_test_h(0) == view_from_h(0));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
EXPECT_TRUE(view_from_h(0) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_from_h(1) == ValueType{-1});
|
||||||
|
|
||||||
|
EXPECT_TRUE(view_test_h(0) == new_value);
|
||||||
|
EXPECT_TRUE(view_test_h(1) == view_from_h(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < view_test_h.extent(0); ++i) {
|
||||||
|
if (i == 0 || i == 3 || i == 5 || i == 6) {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == new_value);
|
||||||
|
} else {
|
||||||
|
const auto gold = ValueType{-5} + static_cast<ValueType>(i + 1);
|
||||||
|
EXPECT_TRUE(view_from_h(i) == gold);
|
||||||
|
EXPECT_TRUE(view_test_h(i) == gold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < view_test_h.extent(0); ++i) {
|
||||||
|
if (i < 4) {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{-1});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == view_from_h(i));
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == new_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < view_test_h.extent(0); ++i) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{-1});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == view_from_h(i));
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(view_from_h(i) == ValueType{2});
|
||||||
|
EXPECT_TRUE(view_test_h(i) == new_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct EqualsTwoFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
bool operator()(const ValueType val) const { return (val == ValueType(2)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "replace_copy_if: " << name << ", " <<
|
||||||
|
// view_tag_to_string(Tag{})
|
||||||
|
// << ", " << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
ValueType new_value{43};
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_if_from");
|
||||||
|
using pred_type = EqualsTwoFunctor<ValueType>;
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_if_dest");
|
||||||
|
auto rit = KE::replace_copy_if(exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
pred_type(), new_value);
|
||||||
|
verify_data(name, view_from, view_dest, new_value);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_if_dest");
|
||||||
|
auto rit = KE::replace_copy_if("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest),
|
||||||
|
pred_type(), new_value);
|
||||||
|
verify_data(name, view_from, view_dest, new_value);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_if_dest");
|
||||||
|
auto rit = KE::replace_copy_if(exespace(), view_from, view_dest,
|
||||||
|
pred_type(), new_value);
|
||||||
|
verify_data(name, view_from, view_dest, new_value);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(view_from, name);
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_copy_if_dest");
|
||||||
|
auto rit = KE::replace_copy_if("label", exespace(), view_from, view_dest,
|
||||||
|
pred_type(), new_value);
|
||||||
|
verify_data(name, view_from, view_dest, new_value);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 1103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_replace_ops_test, replace_copy_if) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ReplaceCopyIf
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
257
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsReplaceIf.cpp
Normal file
257
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsReplaceIf.cpp
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace ReplaceIf {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-20., 20.) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-100, 100) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = value_type{-5} + static_cast<value_type>(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
v_h(5) = static_cast<value_type>(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// my own because std::replace_if is ONLY found with std=c++20
|
||||||
|
template <class ForwardIt, class UnaryPredicate, class T>
|
||||||
|
void my_host_replace_if(ForwardIt first, ForwardIt last, UnaryPredicate p,
|
||||||
|
const T& new_value) {
|
||||||
|
for (; first != last; ++first) {
|
||||||
|
if (p(*first)) {
|
||||||
|
*first = new_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2, class ValueType,
|
||||||
|
class PredicateType>
|
||||||
|
void verify_data(ViewType1 data_view, // contains data
|
||||||
|
ViewType2 test_view, // the view to test
|
||||||
|
ValueType new_value, PredicateType pred) {
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
|
||||||
|
auto data_view_dc = create_deep_copyable_compatible_clone(data_view);
|
||||||
|
auto data_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), data_view_dc);
|
||||||
|
my_host_replace_if(KE::begin(data_view_h), KE::end(data_view_h), pred,
|
||||||
|
new_value);
|
||||||
|
|
||||||
|
auto test_view_dc = create_deep_copyable_compatible_clone(test_view);
|
||||||
|
auto test_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), test_view_dc);
|
||||||
|
|
||||||
|
if (test_view_h.extent(0) > 0) {
|
||||||
|
for (std::size_t i = 0; i < test_view_h.extent(0); ++i) {
|
||||||
|
// std::cout << i << " " << std::setprecision(15)
|
||||||
|
// << data_view_dc(i) << " "
|
||||||
|
// << data_view_h(i) << " "
|
||||||
|
// << test_view_h(i) << std::endl;
|
||||||
|
EXPECT_TRUE(data_view_h(i) == test_view_h(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class PredicateType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info, PredicateType pred) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "replace_if: " << name << ", " << view_tag_to_string(Tag{})
|
||||||
|
// << ", " << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
ValueType new_value{23};
|
||||||
|
auto view_with_data =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "replace_if_v2");
|
||||||
|
auto view_to_test = create_view<ValueType>(Tag{}, view_ext, "replace_if_v1");
|
||||||
|
fill_view(view_with_data, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
CopyFunctor<decltype(view_with_data), decltype(view_to_test)> F1(
|
||||||
|
view_with_data, view_to_test);
|
||||||
|
Kokkos::parallel_for("copy", view_to_test.extent(0), F1);
|
||||||
|
|
||||||
|
KE::replace_if(exespace(), KE::begin(view_to_test), KE::end(view_to_test),
|
||||||
|
pred, new_value);
|
||||||
|
verify_data(view_with_data, view_to_test, new_value, pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CopyFunctor<decltype(view_with_data), decltype(view_to_test)> F1(
|
||||||
|
view_with_data, view_to_test);
|
||||||
|
Kokkos::parallel_for("copy", view_to_test.extent(0), F1);
|
||||||
|
|
||||||
|
KE::replace_if("label", exespace(), KE::begin(view_to_test),
|
||||||
|
KE::end(view_to_test), pred, new_value);
|
||||||
|
verify_data(view_with_data, view_to_test, new_value, pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CopyFunctor<decltype(view_with_data), decltype(view_to_test)> F1(
|
||||||
|
view_with_data, view_to_test);
|
||||||
|
Kokkos::parallel_for("copy", view_to_test.extent(0), F1);
|
||||||
|
|
||||||
|
KE::replace_if(exespace(), view_to_test, pred, new_value);
|
||||||
|
verify_data(view_with_data, view_to_test, new_value, pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CopyFunctor<decltype(view_with_data), decltype(view_to_test)> F1(
|
||||||
|
view_with_data, view_to_test);
|
||||||
|
Kokkos::parallel_for("copy", view_to_test.extent(0), F1);
|
||||||
|
|
||||||
|
KE::replace_if("label", exespace(), view_to_test, pred, new_value);
|
||||||
|
verify_data(view_with_data, view_to_test, new_value, pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element", 1}, {"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2}, {"small-a", 9}, {"small-b", 13},
|
||||||
|
{"medium", 1103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
using pred_p_t = IsPositiveFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, pred_p_t{});
|
||||||
|
using pred_n_t = IsNegativeFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, pred_n_t{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_replace_ops_test, replace_if) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ReplaceIf
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
180
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsReverse.cpp
Normal file
180
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsReverse.cpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Reverse {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a" || name == "small-b" || name == "medium" ||
|
||||||
|
name == "large") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(-11) + static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2>
|
||||||
|
void verify_data(ViewType1 test_view, ViewType2 orig_view) {
|
||||||
|
auto tv_h = create_host_space_copy(test_view);
|
||||||
|
auto ov_h = create_host_space_copy(orig_view);
|
||||||
|
|
||||||
|
const std::size_t ext = test_view.extent(0);
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
EXPECT_TRUE(tv_h(i) == ov_h(ext - i - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "reverse: " << name << ", " << view_tag_to_string(Tag{}) << ",
|
||||||
|
// "
|
||||||
|
// << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
auto test_view = create_view<ValueType>(Tag{}, view_ext, "reverse");
|
||||||
|
auto orig_view = create_view<ValueType>(Tag{}, view_ext, "reverse");
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(test_view, name);
|
||||||
|
fill_view(orig_view, name);
|
||||||
|
KE::reverse(exespace(), KE::begin(test_view), KE::end(test_view));
|
||||||
|
verify_data(test_view, orig_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(test_view, name);
|
||||||
|
fill_view(orig_view, name);
|
||||||
|
KE::reverse("label", exespace(), KE::begin(test_view), KE::end(test_view));
|
||||||
|
verify_data(test_view, orig_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(test_view, name);
|
||||||
|
fill_view(orig_view, name);
|
||||||
|
KE::reverse(exespace(), test_view);
|
||||||
|
verify_data(test_view, orig_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(test_view, name);
|
||||||
|
fill_view(orig_view, name);
|
||||||
|
KE::reverse("label", exespace(), test_view);
|
||||||
|
verify_data(test_view, orig_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 1103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_modseq_test, reverse) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Reverse
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
275
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRotate.cpp
Normal file
275
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRotate.cpp
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Rotate {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-50, 50) { m_gen.seed(1034343); }
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-90., 100.) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(0);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(-2);
|
||||||
|
v_h(4) = static_cast<value_type>(3);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(-40);
|
||||||
|
v_h(7) = static_cast<value_type>(4);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(62);
|
||||||
|
v_h(10) = static_cast<value_type>(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(-1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(-3);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(4);
|
||||||
|
v_h(7) = static_cast<value_type>(24);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(-46);
|
||||||
|
v_h(10) = static_cast<value_type>(8);
|
||||||
|
v_h(11) = static_cast<value_type>(9);
|
||||||
|
v_h(12) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType, class ResultIt, class ViewHostType>
|
||||||
|
void verify_data(ResultIt result_it, ViewType view, ViewHostType data_view_host,
|
||||||
|
std::size_t rotation_point) {
|
||||||
|
// run std::rotate
|
||||||
|
auto n_it = KE::begin(data_view_host) + rotation_point;
|
||||||
|
auto std_rit =
|
||||||
|
std::rotate(KE::begin(data_view_host), n_it, KE::end(data_view_host));
|
||||||
|
|
||||||
|
// make sure results match
|
||||||
|
const auto my_diff = result_it - KE::begin(view);
|
||||||
|
const auto std_diff = std_rit - KE::begin(data_view_host);
|
||||||
|
EXPECT_TRUE(my_diff == std_diff);
|
||||||
|
|
||||||
|
// check views match
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
const std::size_t ext = view_h.extent(0);
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
EXPECT_TRUE(view_h(i) == data_view_host[i]);
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << "mine: " << view_h(i) << " "
|
||||||
|
// << "std: " << data_view_host(i)
|
||||||
|
// << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name,
|
||||||
|
std::size_t rotation_point) {
|
||||||
|
std::cout << "rotate: "
|
||||||
|
<< " at " << rotation_point << ", " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << ", "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info,
|
||||||
|
std::size_t rotation_point) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, rotation_point);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "rotate_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE rotate or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto n_it = KE::begin(view) + rotation_point;
|
||||||
|
auto rit = KE::rotate(exespace(), KE::begin(view), n_it, KE::end(view));
|
||||||
|
verify_data(rit, view, view_h, rotation_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "rotate_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE rotate or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto n_it = KE::begin(view) + rotation_point;
|
||||||
|
auto rit =
|
||||||
|
KE::rotate("label", exespace(), KE::begin(view), n_it, KE::end(view));
|
||||||
|
verify_data(rit, view, view_h, rotation_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "rotate_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE rotate or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::rotate(exespace(), view, rotation_point);
|
||||||
|
// verify_data(rit, view, view_h, rotation_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "rotate_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE rotate or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::rotate("label", exespace(), view, rotation_point);
|
||||||
|
verify_data(rit, view, view_h, rotation_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 11},
|
||||||
|
{"small-b", 13}, {"medium", 21103}, {"large", 101513}};
|
||||||
|
|
||||||
|
std::vector<std::size_t> rotation_points = {0, 1, 2, 3, 8,
|
||||||
|
56, 101, 1003, 101501};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
for (const auto& it2 : rotation_points) {
|
||||||
|
// for each view scenario, we rotate at multiple points
|
||||||
|
// but only if the view has an extent that is >= rotation point
|
||||||
|
const auto view_ext = it.second;
|
||||||
|
if (view_ext >= it2) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, rotate) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Rotate
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
275
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRotateCopy.cpp
Normal file
275
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsRotateCopy.cpp
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace RotateCopy {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-50, 50) { m_gen.seed(1034343); }
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-90., 100.) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(0);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(3);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(4);
|
||||||
|
v_h(7) = static_cast<value_type>(4);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(6);
|
||||||
|
v_h(10) = static_cast<value_type>(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(3);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(4);
|
||||||
|
v_h(7) = static_cast<value_type>(4);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(6);
|
||||||
|
v_h(10) = static_cast<value_type>(8);
|
||||||
|
v_h(11) = static_cast<value_type>(9);
|
||||||
|
v_h(12) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeFrom, class ViewTypeTest>
|
||||||
|
void verify_data(ViewTypeFrom view_from, ViewTypeTest view_test,
|
||||||
|
std::size_t rotation_point) {
|
||||||
|
auto view_from_h = create_host_space_copy(view_from);
|
||||||
|
auto view_test_h = create_host_space_copy(view_test);
|
||||||
|
const std::size_t ext = view_test_h.extent(0);
|
||||||
|
|
||||||
|
using value_type = typename ViewTypeTest::value_type;
|
||||||
|
std::vector<value_type> std_gold_h(ext);
|
||||||
|
auto first_n = KE::cbegin(view_from_h) + rotation_point;
|
||||||
|
std::rotate_copy(KE::cbegin(view_from_h), first_n, KE::cend(view_from_h),
|
||||||
|
std_gold_h.begin());
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
EXPECT_TRUE(view_test_h(i) == std_gold_h[i]);
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << "from: " << view_from_h(i) << " "
|
||||||
|
// << "mine: " << view_test_h(i) << " "
|
||||||
|
// << "std: " << std_gold_h[i]
|
||||||
|
// << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name,
|
||||||
|
std::size_t rotation_point) {
|
||||||
|
std::cout << "rotate_copy: "
|
||||||
|
<< " at " << rotation_point << ", " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << ", "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info,
|
||||||
|
std::size_t rotation_point) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, rotation_point);
|
||||||
|
|
||||||
|
auto view_from = create_view<ValueType>(Tag{}, view_ext, "rotate_copy_from");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "rotate_copy_dest");
|
||||||
|
auto n_it = KE::cbegin(view_from) + rotation_point;
|
||||||
|
auto rit = KE::rotate_copy(exespace(), KE::cbegin(view_from), n_it,
|
||||||
|
KE::cend(view_from), KE::begin(view_dest));
|
||||||
|
verify_data(view_from, view_dest, rotation_point);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "rotate_copy_dest");
|
||||||
|
auto n_it = KE::cbegin(view_from) + rotation_point;
|
||||||
|
auto rit = KE::rotate_copy("label", exespace(), KE::cbegin(view_from), n_it,
|
||||||
|
KE::cend(view_from), KE::begin(view_dest));
|
||||||
|
verify_data(view_from, view_dest, rotation_point);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "rotate_copy_dest");
|
||||||
|
auto rit =
|
||||||
|
KE::rotate_copy(exespace(), view_from, rotation_point, view_dest);
|
||||||
|
verify_data(view_from, view_dest, rotation_point);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "rotate_copy_dest");
|
||||||
|
auto rit = KE::rotate_copy("label", exespace(), view_from, rotation_point,
|
||||||
|
view_dest);
|
||||||
|
verify_data(view_from, view_dest, rotation_point);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + view_ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 11},
|
||||||
|
{"small-b", 13}, {"medium", 21103}, {"large", 101513}};
|
||||||
|
|
||||||
|
std::vector<std::size_t> rotation_points = {0, 1, 2, 3, 8,
|
||||||
|
56, 101, 1003, 101501};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
for (const auto& it2 : rotation_points) {
|
||||||
|
// for each view scenario, we rotate at multiple points
|
||||||
|
// but only if the view has an extent that is >= rotation point
|
||||||
|
const auto view_ext = it.second;
|
||||||
|
if (view_ext >= it2) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, rotate_copy) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace RotateCopy
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <TestStdAlgorithmsHelperFunctors.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_MinMaxElementOperations.hpp>
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = (value_type)i;
|
||||||
|
}
|
||||||
|
v_h(ext / 2) = (value_type)-101;
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType, class IndexType, class ReducerType>
|
||||||
|
struct MyFunctor {
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
|
||||||
|
ViewType m_view;
|
||||||
|
ReducerType m_reducer;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const IndexType i, red_value_type& red_value) const {
|
||||||
|
m_reducer.join(red_value, red_value_type{m_view(i), i});
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
MyFunctor(ViewType view, ReducerType reducer)
|
||||||
|
: m_view(view), m_reducer(std::move(reducer)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(scalar_vs_view_red, use_scalar) {
|
||||||
|
using exe_space = Kokkos::DefaultExecutionSpace;
|
||||||
|
using index_type = int;
|
||||||
|
using scalar_type = int;
|
||||||
|
using view_type = Kokkos::View<scalar_type*, exe_space>;
|
||||||
|
|
||||||
|
const auto ext = 10001;
|
||||||
|
view_type view("myview", ext);
|
||||||
|
fill_view(view);
|
||||||
|
|
||||||
|
using reducer_type = ::Kokkos::MinLoc<scalar_type, index_type>;
|
||||||
|
using red_result_type = typename reducer_type::value_type;
|
||||||
|
using func_type = MyFunctor<view_type, index_type, reducer_type>;
|
||||||
|
red_result_type result;
|
||||||
|
reducer_type reducer(result);
|
||||||
|
Kokkos::parallel_reduce("MinLocReduce",
|
||||||
|
Kokkos::RangePolicy<exe_space>(exe_space(), 0, ext),
|
||||||
|
func_type(view, reducer), reducer);
|
||||||
|
std::cout << " use_scalar = " << result.val << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class IteratorType, class ReducerType>
|
||||||
|
struct StdMyMinFunctor {
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
|
||||||
|
IteratorType m_first;
|
||||||
|
ReducerType m_reducer;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const index_type i, red_value_type& red_value) const {
|
||||||
|
m_reducer.join(red_value, red_value_type{m_first[i], i});
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdMyMinFunctor(IteratorType first, ReducerType reducer)
|
||||||
|
: m_first(std::move(first)), m_reducer(std::move(reducer)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType, class ReducerType>
|
||||||
|
struct StdMyMinFunctor2 {
|
||||||
|
using red_value_type = typename ReducerType::value_type;
|
||||||
|
|
||||||
|
ViewType m_view;
|
||||||
|
ReducerType m_reducer;
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
void operator()(const std::size_t i, red_value_type& red_value) const {
|
||||||
|
m_reducer.join(red_value, red_value_type{m_view(i), i});
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_FUNCTION
|
||||||
|
StdMyMinFunctor2(ViewType viewIn, ReducerType reducer)
|
||||||
|
: m_view(viewIn), m_reducer(std::move(reducer)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
IteratorType my_min_1(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
using value_type = typename IteratorType::value_type;
|
||||||
|
using reducer_type =
|
||||||
|
Kokkos::MinFirstLoc<value_type, index_type, ExecutionSpace>;
|
||||||
|
using result_view_type = typename reducer_type::result_view_type;
|
||||||
|
using func_t = StdMyMinFunctor<IteratorType, reducer_type>;
|
||||||
|
|
||||||
|
result_view_type result("min_or_max_elem_impl_result");
|
||||||
|
reducer_type reducer(result);
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
::Kokkos::parallel_reduce(
|
||||||
|
"label", Kokkos::RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_t(first, reducer), reducer);
|
||||||
|
const auto result_h =
|
||||||
|
::Kokkos::create_mirror_view_and_copy(::Kokkos::HostSpace(), result);
|
||||||
|
return first + result_h().loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class IteratorType>
|
||||||
|
IteratorType my_min_2(const ExecutionSpace& ex, IteratorType first,
|
||||||
|
IteratorType last) {
|
||||||
|
using index_type = typename IteratorType::difference_type;
|
||||||
|
using value_type = typename IteratorType::value_type;
|
||||||
|
using reducer_type = Kokkos::MinFirstLoc<value_type, index_type>;
|
||||||
|
using result_type = typename reducer_type::value_type;
|
||||||
|
using func_t = StdMyMinFunctor<IteratorType, reducer_type>;
|
||||||
|
|
||||||
|
result_type result;
|
||||||
|
reducer_type reducer(result);
|
||||||
|
const auto num_elements = Kokkos::Experimental::distance(first, last);
|
||||||
|
::Kokkos::parallel_reduce(
|
||||||
|
"label", Kokkos::RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_t(first, reducer), reducer);
|
||||||
|
return first + result.loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExecutionSpace, class ViewType>
|
||||||
|
std::size_t my_min_3(const ExecutionSpace& ex, ViewType view) {
|
||||||
|
using index_type = std::size_t;
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using reducer_type = Kokkos::MinFirstLoc<value_type, index_type>;
|
||||||
|
using result_type = typename reducer_type::value_type;
|
||||||
|
using func_t = StdMyMinFunctor2<ViewType, reducer_type>;
|
||||||
|
|
||||||
|
result_type result;
|
||||||
|
reducer_type reducer(result);
|
||||||
|
const auto num_elements = view.extent(0);
|
||||||
|
::Kokkos::parallel_reduce(
|
||||||
|
"label", Kokkos::RangePolicy<ExecutionSpace>(ex, 0, num_elements),
|
||||||
|
func_t(view, reducer), reducer);
|
||||||
|
return result.loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(scalar_vs_view_red, my_min_it_use_result_view) {
|
||||||
|
using exe_space = Kokkos::DefaultExecutionSpace;
|
||||||
|
using view_type = Kokkos::View<int*, exe_space>;
|
||||||
|
view_type view("myview", 10001);
|
||||||
|
fill_view(view);
|
||||||
|
|
||||||
|
auto rit = my_min_1(exe_space(), KE::cbegin(view), KE::cend(view));
|
||||||
|
std::cout << " my_min_el = " << KE::distance(KE::cbegin(view), rit) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(scalar_vs_view_red, my_min_no_it_use_result_scalar) {
|
||||||
|
using exe_space = Kokkos::DefaultExecutionSpace;
|
||||||
|
using view_type = Kokkos::View<int*, exe_space>;
|
||||||
|
view_type view("myview", 10001);
|
||||||
|
fill_view(view);
|
||||||
|
|
||||||
|
auto ind = my_min_3(exe_space(), view);
|
||||||
|
std::cout << " my_min_el = " << ind << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(scalar_vs_view_red, my_min_it_use_result_scalar) {
|
||||||
|
using exe_space = Kokkos::DefaultExecutionSpace;
|
||||||
|
using view_type = Kokkos::View<int*, exe_space>;
|
||||||
|
view_type view("myview", 10001);
|
||||||
|
fill_view(view);
|
||||||
|
|
||||||
|
auto rit = my_min_2(exe_space(), KE::cbegin(view), KE::cend(view));
|
||||||
|
std::cout << " my_min_el = " << KE::distance(KE::cbegin(view), rit) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
364
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsSearch.cpp
Normal file
364
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsSearch.cpp
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Search {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(0, 20) { m_gen.seed(1034343); }
|
||||||
|
UnifDist(int a, int b) : m_dist(a, b) { m_gen.seed(234343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "three-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(-1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
v_h(2) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "three-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(3);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "four-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(-1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
v_h(2) = static_cast<value_type>(2);
|
||||||
|
v_h(3) = static_cast<value_type>(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "four-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(0);
|
||||||
|
v_h(1) = static_cast<value_type>(4);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(-1);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(1);
|
||||||
|
v_h(7) = static_cast<value_type>(2);
|
||||||
|
v_h(8) = static_cast<value_type>(2);
|
||||||
|
v_h(9) = static_cast<value_type>(4);
|
||||||
|
v_h(10) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
v_h(2) = static_cast<value_type>(3);
|
||||||
|
v_h(3) = static_cast<value_type>(1);
|
||||||
|
v_h(4) = static_cast<value_type>(-1);
|
||||||
|
v_h(5) = static_cast<value_type>(-2);
|
||||||
|
v_h(6) = static_cast<value_type>(0);
|
||||||
|
v_h(7) = static_cast<value_type>(1);
|
||||||
|
v_h(8) = static_cast<value_type>(2);
|
||||||
|
v_h(9) = static_cast<value_type>(2);
|
||||||
|
v_h(10) = static_cast<value_type>(5);
|
||||||
|
v_h(11) = static_cast<value_type>(9);
|
||||||
|
v_h(12) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
auto create_seq_to_search(ViewType data_view, std::size_t seq_extent) {
|
||||||
|
// for the search, we need to specify a sequence that we search for
|
||||||
|
// within the original view/range.
|
||||||
|
// to do this, rather than doing something purely random,
|
||||||
|
// we use the view with the data, and select a subsequence.
|
||||||
|
|
||||||
|
auto data_view_h = create_host_space_copy(data_view);
|
||||||
|
const auto data_view_extent = data_view.extent(0);
|
||||||
|
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
using seq_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
seq_view_t seq_view("seq_view", seq_extent);
|
||||||
|
auto seq_view_h = create_mirror_view(Kokkos::HostSpace(), seq_view);
|
||||||
|
|
||||||
|
// when the target sequence is of same size as view, just fill
|
||||||
|
// sequeunce with all values of the view
|
||||||
|
if (seq_extent == data_view_extent) {
|
||||||
|
for (std::size_t i = 0; i < seq_extent; ++i) {
|
||||||
|
seq_view_h(i) = data_view_h(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if target sequence to fill is smaller, then we need to pick
|
||||||
|
// a starting point to copy data from to make the the sequence.
|
||||||
|
// we pick randomly between 0 and data_view_extent - seq_extent.
|
||||||
|
// and fill the sequeunce data with the values copied from data view.
|
||||||
|
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::random_device r;
|
||||||
|
// from this:
|
||||||
|
// https://stackoverflow.com/questions/34490599/c11-how-to-set-seed-using-random
|
||||||
|
std::seed_seq seed{r(), r(), r(), r(), r(), r()};
|
||||||
|
std::mt19937 gen(seed);
|
||||||
|
dist_type dist(0, data_view_extent - seq_extent);
|
||||||
|
const auto start = dist(gen);
|
||||||
|
// std::cout << "start= " << start << "\n";
|
||||||
|
for (std::size_t i = 0; i < seq_extent; ++i) {
|
||||||
|
seq_view_h(i) = data_view_h(start + i);
|
||||||
|
// std::cout << "i= " << i << " " << seq_view_h(i) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(seq_view, seq_view_h);
|
||||||
|
return seq_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search is only avai from c++17, so I have to put it here
|
||||||
|
template <class ForwardIt1, class ForwardIt2, class BinaryPredicate>
|
||||||
|
ForwardIt1 my_std_search(ForwardIt1 first, ForwardIt1 last, ForwardIt2 s_first,
|
||||||
|
ForwardIt2 s_last, BinaryPredicate p) {
|
||||||
|
for (;; ++first) {
|
||||||
|
ForwardIt1 it = first;
|
||||||
|
for (ForwardIt2 s_it = s_first;; ++it, ++s_it) {
|
||||||
|
if (s_it == s_last) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
if (it == last) {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
if (!p(*it, *s_it)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// search is only avai from c++17, so I have to put it here
|
||||||
|
template <class ForwardIt1, class ForwardIt2>
|
||||||
|
ForwardIt1 my_std_search(ForwardIt1 first, ForwardIt1 last, ForwardIt2 s_first,
|
||||||
|
ForwardIt2 s_last) {
|
||||||
|
using value_type1 = typename ForwardIt1::value_type;
|
||||||
|
using value_type2 = typename ForwardIt2::value_type;
|
||||||
|
|
||||||
|
using pred_t = IsEqualFunctor<value_type1, value_type2>;
|
||||||
|
return my_std_search(first, last, s_first, s_last, pred_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t seq_ext) {
|
||||||
|
std::cout << "search: default predicate: " << name << ", "
|
||||||
|
<< "search_seq_ext = " << seq_ext << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class Predicate>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t seq_ext,
|
||||||
|
Predicate pred) {
|
||||||
|
(void)pred;
|
||||||
|
std::cout << "search: custom predicate: " << name << ", "
|
||||||
|
<< "search_seq_ext = " << seq_ext << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class... Args>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info, std::size_t seq_ext,
|
||||||
|
Args... args) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, seq_ext, args...);
|
||||||
|
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "search_test_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
auto s_view = create_seq_to_search(view, seq_ext);
|
||||||
|
|
||||||
|
// run std
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto s_view_h = create_host_space_copy(s_view);
|
||||||
|
auto stdrit =
|
||||||
|
my_std_search(KE::cbegin(view_h), KE::cend(view_h), KE::cbegin(s_view_h),
|
||||||
|
KE::cend(s_view_h), args...);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::search(exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::cbegin(s_view), KE::cend(s_view), args...);
|
||||||
|
const auto mydiff = myrit - KE::cbegin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit =
|
||||||
|
KE::search("label", exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
KE::cbegin(s_view), KE::cend(s_view), args...);
|
||||||
|
const auto mydiff = myrit - KE::cbegin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::search(exespace(), view, s_view, args...);
|
||||||
|
const auto mydiff = myrit - KE::begin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::search("label", exespace(), view, s_view, args...);
|
||||||
|
const auto mydiff = myrit - KE::begin(view);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {{"empty", 0},
|
||||||
|
{"one-element-a", 1},
|
||||||
|
{"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2},
|
||||||
|
{"three-elements-a", 3},
|
||||||
|
{"three-elements-b", 3},
|
||||||
|
{"four-elements-a", 4},
|
||||||
|
{"four-elements-b", 4},
|
||||||
|
{"small-a", 11},
|
||||||
|
{"small-b", 13},
|
||||||
|
{"medium-a", 11103},
|
||||||
|
{"medium-b", 21103},
|
||||||
|
{"large-a", 101513},
|
||||||
|
{"large-b", 100111}};
|
||||||
|
|
||||||
|
const std::vector<std::size_t> seq_extents = {
|
||||||
|
0, 1, 2, 3, 4, 5, 8, 11, 15, 31, 113, 523, 1035, 11103};
|
||||||
|
|
||||||
|
// for each scenario we want to run "search"
|
||||||
|
// for a set of sequences of various extents
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
for (const auto& it2 : seq_extents) {
|
||||||
|
// only run if view is larger or equal than sequence to search for
|
||||||
|
if (it.second >= it2) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2);
|
||||||
|
|
||||||
|
using func_t = IsEqualFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2, func_t());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_non_mod_seq_ops, search) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Search
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
336
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsSearch_n.cpp
Normal file
336
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsSearch_n.cpp
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Search_n {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
// search_n is only available from c++20, so I have to put it here
|
||||||
|
template <class ForwardIt, class Size, class T, class BinaryPredicate>
|
||||||
|
ForwardIt my_std_search_n(ForwardIt first, ForwardIt last, Size count,
|
||||||
|
const T& value, BinaryPredicate p) {
|
||||||
|
if (count <= 0) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
for (; first != last; ++first) {
|
||||||
|
if (!p(*first, value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ForwardIt candidate = first;
|
||||||
|
Size cur_count = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
++cur_count;
|
||||||
|
if (cur_count >= count) {
|
||||||
|
// success
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
++first;
|
||||||
|
if (first == last) {
|
||||||
|
// exhausted the list
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
if (!p(*first, value)) {
|
||||||
|
// too few in a row
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ForwardIt, class Size, class T>
|
||||||
|
ForwardIt my_std_search_n(ForwardIt first, ForwardIt last, Size count,
|
||||||
|
const T& value) {
|
||||||
|
using iter_value_type = typename ForwardIt::value_type;
|
||||||
|
using p_type = IsEqualFunctor<iter_value_type, T>;
|
||||||
|
return my_std_search_n(first, last, count, value, p_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(0, 20) { m_gen.seed(1034343); }
|
||||||
|
UnifDist(int a, int b) : m_dist(a, b) { m_gen.seed(234343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType, class ValueType>
|
||||||
|
void fill_view(ViewType dest_view, ValueType value, std::size_t count,
|
||||||
|
const std::string& where_to_place_count_values) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
// fill with something
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (where_to_place_count_values == "none") {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (where_to_place_count_values == "left") {
|
||||||
|
for (std::size_t i = 0; i < count; ++i) {
|
||||||
|
v_h(i) = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (where_to_place_count_values == "left_and_1567") {
|
||||||
|
for (std::size_t i = 0; i < count; ++i) {
|
||||||
|
v_h(i) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < count; ++i) {
|
||||||
|
v_h(1567 + i) = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (where_to_place_count_values == "random") {
|
||||||
|
// find a random location to start filling view
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::random_device r;
|
||||||
|
// from this:
|
||||||
|
// https://stackoverflow.com/questions/34490599/c11-how-to-set-seed-using-random
|
||||||
|
std::seed_seq seed{r(), r(), r(), r(), r(), r()};
|
||||||
|
std::mt19937 gen(seed);
|
||||||
|
dist_type dist(0, ext - count);
|
||||||
|
const auto start_at = dist(gen);
|
||||||
|
// std::cout << "start_at " << start_at << std::endl;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < count; ++i) {
|
||||||
|
v_h(start_at + i) = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (where_to_place_count_values == "11133_and_right") {
|
||||||
|
for (std::size_t i = 0; i < count; ++i) {
|
||||||
|
v_h(11133 + i) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < count; ++i) {
|
||||||
|
v_h(ext - count + i) = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (where_to_place_count_values == "right") {
|
||||||
|
for (std::size_t i = 0; i < count; ++i) {
|
||||||
|
v_h(ext - count + i) = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Kokkos: test: search_n: this should not happen");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t count,
|
||||||
|
const std::string& where_to_place_count_values) {
|
||||||
|
std::cout << "search_n: default predicate: " << name << ", "
|
||||||
|
<< "count = " << count << ", " << where_to_place_count_values
|
||||||
|
<< ", " << view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class Predicate>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t count,
|
||||||
|
const std::string& where_to_place_count_values,
|
||||||
|
Predicate pred) {
|
||||||
|
(void)pred;
|
||||||
|
std::cout << "search_n: custom predicate: " << name << ", "
|
||||||
|
<< "count = " << count << ", " << where_to_place_count_values
|
||||||
|
<< ", " << view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class... Args>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info, std::size_t count,
|
||||||
|
ValueType value, Args... args) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
const auto count_place = std::get<2>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, count, count_place, args...);
|
||||||
|
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "search_n_test_view");
|
||||||
|
fill_view(view, value, count, count_place);
|
||||||
|
|
||||||
|
// run std
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto stdrit = my_std_search_n(KE::cbegin(view_h), KE::cend(view_h), count,
|
||||||
|
value, args...);
|
||||||
|
const auto stddiff = stdrit - KE::cbegin(view_h);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::search_n(exespace(), KE::cbegin(view), KE::cend(view),
|
||||||
|
count, value, args...);
|
||||||
|
const auto mydiff = myrit - KE::cbegin(view);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::search_n("label", exespace(), KE::cbegin(view),
|
||||||
|
KE::cend(view), count, value, args...);
|
||||||
|
const auto mydiff = myrit - KE::cbegin(view);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::search_n("label", exespace(), view, count, value, args...);
|
||||||
|
const auto mydiff = myrit - KE::begin(view);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto myrit = KE::search_n(exespace(), view, count, value, args...);
|
||||||
|
const auto mydiff = myrit - KE::begin(view);
|
||||||
|
EXPECT_TRUE(mydiff == stddiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
using scenario_t = std::tuple<std::string, std::size_t, std::string>;
|
||||||
|
std::vector<scenario_t> scenarios(31);
|
||||||
|
scenarios[0] = scenario_t("empty", 0u, "none");
|
||||||
|
scenarios[1] = scenario_t("one-element-a", 1u, "none");
|
||||||
|
scenarios[2] = scenario_t("one-element-b", 1u, "left");
|
||||||
|
|
||||||
|
scenarios[3] = scenario_t("two-elements-a", 2u, "none");
|
||||||
|
scenarios[4] = scenario_t("two-elements-b", 2u, "left");
|
||||||
|
scenarios[5] = scenario_t("two-elements-c", 2u, "right");
|
||||||
|
|
||||||
|
scenarios[6] = scenario_t("three-elements-a", 3u, "none");
|
||||||
|
scenarios[7] = scenario_t("three-elements-b", 3u, "left");
|
||||||
|
scenarios[8] = scenario_t("three-elements-c", 3u, "random");
|
||||||
|
scenarios[9] = scenario_t("three-elements-d", 3u, "right");
|
||||||
|
|
||||||
|
scenarios[10] = scenario_t("four-elements-a", 4u, "none");
|
||||||
|
scenarios[11] = scenario_t("four-elements-b", 4u, "left");
|
||||||
|
scenarios[12] = scenario_t("four-elements-c", 4u, "random");
|
||||||
|
scenarios[13] = scenario_t("four-elements-d", 4u, "right");
|
||||||
|
|
||||||
|
scenarios[14] = scenario_t("small-a", 13u, "none");
|
||||||
|
scenarios[15] = scenario_t("small-b", 13u, "left");
|
||||||
|
scenarios[16] = scenario_t("small-c", 13u, "random");
|
||||||
|
scenarios[17] = scenario_t("small-d", 13u, "right");
|
||||||
|
scenarios[18] = scenario_t("small-e", 131u, "none");
|
||||||
|
scenarios[19] = scenario_t("small-f", 131u, "left");
|
||||||
|
scenarios[20] = scenario_t("small-g", 131u, "random");
|
||||||
|
scenarios[21] = scenario_t("small-h", 131u, "right");
|
||||||
|
|
||||||
|
scenarios[22] = scenario_t("medium-a", 21103u, "none");
|
||||||
|
scenarios[22] = scenario_t("medium-b", 21103u, "left");
|
||||||
|
scenarios[23] = scenario_t("medium-c", 21103u, "random");
|
||||||
|
scenarios[24] = scenario_t("medium-d", 21103u, "right");
|
||||||
|
scenarios[25] = scenario_t("medium-e", 21103u, "left_and_1567");
|
||||||
|
scenarios[26] = scenario_t("medium-f", 21103u, "11133_and_right");
|
||||||
|
|
||||||
|
scenarios[27] = scenario_t("large-a", 101333u, "none");
|
||||||
|
scenarios[28] = scenario_t("large-b", 101333u, "left");
|
||||||
|
scenarios[29] = scenario_t("large-c", 101333u, "random");
|
||||||
|
scenarios[30] = scenario_t("large-d", 101333u, "right");
|
||||||
|
|
||||||
|
const std::vector<std::size_t> counts = {1, 2, 3, 4, 5, 8,
|
||||||
|
11, 13, 31, 131, 523};
|
||||||
|
|
||||||
|
const ValueType target_value = 3;
|
||||||
|
|
||||||
|
// for each view scenario, run "search_n" for multiple counts
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
const std::size_t view_ext = std::get<1>(it);
|
||||||
|
|
||||||
|
if (view_ext == 0) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, 0, target_value);
|
||||||
|
} else {
|
||||||
|
for (const auto& it2 : counts) {
|
||||||
|
// only run if view is larger or equal than count
|
||||||
|
if (view_ext >= it2) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2, target_value);
|
||||||
|
|
||||||
|
using func_t = IsEqualFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2, target_value, func_t());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_non_mod_seq_ops, search_n) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Search_n
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
243
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsShiftLeft.cpp
Normal file
243
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsShiftLeft.cpp
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace ShiftLeft {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-50, 50) { m_gen.seed(1034343); }
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-90., 100.) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ForwardIterator>
|
||||||
|
ForwardIterator my_std_shift_left(
|
||||||
|
ForwardIterator first, ForwardIterator last,
|
||||||
|
typename std::iterator_traits<ForwardIterator>::difference_type n) {
|
||||||
|
// copied from
|
||||||
|
// https://github.com/llvm/llvm-project/blob/main/libcxx/include/__algorithm/shift_left.h
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
ForwardIterator m = first;
|
||||||
|
for (; n > 0; --n) {
|
||||||
|
if (m == last) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
++m;
|
||||||
|
}
|
||||||
|
return std::move(m, last, first);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType, class ResultIt, class ViewHostType>
|
||||||
|
void verify_data(ResultIt result_it, ViewType view, ViewHostType data_view_host,
|
||||||
|
std::size_t shift_value) {
|
||||||
|
auto std_rit = my_std_shift_left(KE::begin(data_view_host),
|
||||||
|
KE::end(data_view_host), shift_value);
|
||||||
|
|
||||||
|
// make sure results match
|
||||||
|
const auto my_diff = result_it - KE::begin(view);
|
||||||
|
const auto std_diff = std_rit - KE::begin(data_view_host);
|
||||||
|
EXPECT_TRUE(my_diff == std_diff);
|
||||||
|
|
||||||
|
// check views match
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
for (std::size_t i = 0; i < (std::size_t)my_diff; ++i) {
|
||||||
|
EXPECT_TRUE(view_h(i) == data_view_host[i]);
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << "mine: " << view_h(i) << " "
|
||||||
|
// << "std: " << data_view_host(i)
|
||||||
|
// << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t shift_value) {
|
||||||
|
std::cout << "shift_left: "
|
||||||
|
<< " by " << shift_value << ", " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << ", "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info,
|
||||||
|
std::size_t shift_value) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, shift_value);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "shift_left_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE shift_left or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit =
|
||||||
|
KE::shift_left(exespace(), KE::begin(view), KE::end(view), shift_value);
|
||||||
|
verify_data(rit, view, view_h, shift_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "shift_left_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE shift_left or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::shift_left("label", exespace(), KE::begin(view),
|
||||||
|
KE::end(view), shift_value);
|
||||||
|
verify_data(rit, view, view_h, shift_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "shift_left_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE shift_left or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::shift_left(exespace(), view, shift_value);
|
||||||
|
verify_data(rit, view, view_h, shift_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view = create_view<ValueType>(Tag{}, view_ext, "shift_left_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE shift_left or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::shift_left("label", exespace(), view, shift_value);
|
||||||
|
verify_data(rit, view, view_h, shift_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {{"empty", 0},
|
||||||
|
{"one-element-a", 1},
|
||||||
|
{"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2},
|
||||||
|
{"three-elements-a", 3},
|
||||||
|
{"three-elements-b", 3},
|
||||||
|
{"small-a", 11},
|
||||||
|
{"small-b", 13},
|
||||||
|
{"medium", 21103},
|
||||||
|
{"large", 101513}};
|
||||||
|
|
||||||
|
// a shift value MUST be non-negative but it does not matter
|
||||||
|
// if it is larger than the view, the algorithm is supposed
|
||||||
|
// to handle that case too
|
||||||
|
std::vector<std::size_t> shifts = {0, 1, 2, 3, 8, 56, 101, 1003, 101501};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
for (const auto& it2 : shifts) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, shift_left) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ShiftLeft
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
247
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsShiftRight.cpp
Normal file
247
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsShiftRight.cpp
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace ShiftRight {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-50, 50) { m_gen.seed(1034343); }
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(-90., 100.) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ForwardIterator>
|
||||||
|
ForwardIterator my_std_shift_right(
|
||||||
|
ForwardIterator first, ForwardIterator last,
|
||||||
|
typename std::iterator_traits<ForwardIterator>::difference_type n) {
|
||||||
|
// copied from
|
||||||
|
// https://github.com/llvm/llvm-project/blob/main/libcxx/include/__algorithm/shift_right.h
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
decltype(n) d = last - first;
|
||||||
|
if (n >= d) {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
ForwardIterator m = first + (d - n);
|
||||||
|
return std::move_backward(first, m, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType, class ResultIt, class ViewHostType>
|
||||||
|
void verify_data(ResultIt result_it, ViewType view, ViewHostType data_view_host,
|
||||||
|
std::size_t shift_value) {
|
||||||
|
auto std_rit = my_std_shift_right(KE::begin(data_view_host),
|
||||||
|
KE::end(data_view_host), shift_value);
|
||||||
|
|
||||||
|
// make sure results match
|
||||||
|
const auto my_diff = KE::end(view) - result_it;
|
||||||
|
const auto std_diff = KE::end(data_view_host) - std_rit;
|
||||||
|
EXPECT_TRUE(my_diff == std_diff);
|
||||||
|
|
||||||
|
// check views match
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto it1 = KE::cbegin(view_h);
|
||||||
|
auto it2 = KE::cbegin(data_view_host);
|
||||||
|
for (std::size_t i = 0; i < (std::size_t)my_diff; ++i) {
|
||||||
|
EXPECT_TRUE(it1[i] == it2[i]);
|
||||||
|
// std::cout << "i= " << i << " "
|
||||||
|
// << "mine: " << it1[i] << " "
|
||||||
|
// << "std: " << it2[i]
|
||||||
|
// << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name, std::size_t shift_value) {
|
||||||
|
std::cout << "shift_right: "
|
||||||
|
<< " by " << shift_value << ", " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << ", "
|
||||||
|
<< value_type_to_string(ValueType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info,
|
||||||
|
std::size_t shift_value) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, shift_value);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "shift_right_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE shift_right or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::shift_right(exespace(), KE::begin(view), KE::end(view),
|
||||||
|
shift_value);
|
||||||
|
verify_data(rit, view, view_h, shift_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "shift_right_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE shift_right or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::shift_right("label", exespace(), KE::begin(view),
|
||||||
|
KE::end(view), shift_value);
|
||||||
|
verify_data(rit, view, view_h, shift_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "shift_right_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE shift_right or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::shift_right(exespace(), view, shift_value);
|
||||||
|
verify_data(rit, view, view_h, shift_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "shift_right_data_view");
|
||||||
|
fill_view(view, name);
|
||||||
|
// create host copy BEFORE shift_right or view will be modified
|
||||||
|
auto view_h = create_host_space_copy(view);
|
||||||
|
auto rit = KE::shift_right("label", exespace(), view, shift_value);
|
||||||
|
verify_data(rit, view, view_h, shift_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {{"empty", 0},
|
||||||
|
{"one-element-a", 1},
|
||||||
|
{"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2},
|
||||||
|
{"three-elements-a", 3},
|
||||||
|
{"three-elements-b", 3},
|
||||||
|
{"small-a", 11},
|
||||||
|
{"small-b", 13},
|
||||||
|
{"medium", 21103},
|
||||||
|
{"large", 101513}};
|
||||||
|
|
||||||
|
// a shift value MUST be non-negative but it does not matter
|
||||||
|
// if it is larger than the view, the algorithm is supposed
|
||||||
|
// to handle that case too
|
||||||
|
std::vector<std::size_t> shifts = {0, 1, 2, 3, 8, 56, 101, 1003, 101501};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
for (const auto& it2 : shifts) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it, it2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, shift_right) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ShiftRight
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,320 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_Numeric.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace TransformEScan {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(0.05, 1.2) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(1, 3) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_zero(ViewType view) {
|
||||||
|
Kokkos::parallel_for(view.extent(0), FillZeroFunctor<ViewType>(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element") {
|
||||||
|
assert(v_h.extent(0) == 1);
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
assert(v_h.extent(0) == 2);
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
assert(v_h.extent(0) == 2);
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
assert(v_h.extent(0) == 9);
|
||||||
|
v_h(0) = static_cast<value_type>(3);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(4);
|
||||||
|
v_h(3) = static_cast<value_type>(1);
|
||||||
|
v_h(4) = static_cast<value_type>(5);
|
||||||
|
v_h(5) = static_cast<value_type>(9);
|
||||||
|
v_h(6) = static_cast<value_type>(2);
|
||||||
|
v_h(7) = static_cast<value_type>(6);
|
||||||
|
v_h(8) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
assert(v_h.extent(0) >= 6);
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
v_h(5) = static_cast<value_type>(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// I had to write my own because std::transform_exclusive_scan is ONLY found
|
||||||
|
// with std=c++17
|
||||||
|
template <class it1, class it2, class ValType, class BopType, class UopType>
|
||||||
|
void my_host_transform_exclusive_scan(it1 first, it1 last, it2 dest,
|
||||||
|
ValType init, BopType bop, UopType uop) {
|
||||||
|
const auto num_elements = last - first;
|
||||||
|
if (num_elements > 0) {
|
||||||
|
while (first < last - 1) {
|
||||||
|
*(dest++) = init;
|
||||||
|
init = bop(uop(*(first++)), init);
|
||||||
|
}
|
||||||
|
*dest = init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2, class ValueType, class BinaryOp,
|
||||||
|
class UnaryOp>
|
||||||
|
void verify_data(ViewType1 data_view, // contains data
|
||||||
|
ViewType2 test_view, // the view to test
|
||||||
|
ValueType init_value, BinaryOp bop, UnaryOp uop) {
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
|
||||||
|
auto data_view_dc = create_deep_copyable_compatible_clone(data_view);
|
||||||
|
auto data_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), data_view_dc);
|
||||||
|
|
||||||
|
using gold_view_value_type = typename ViewType2::value_type;
|
||||||
|
Kokkos::View<gold_view_value_type*, Kokkos::HostSpace> gold_h(
|
||||||
|
"goldh", data_view.extent(0));
|
||||||
|
my_host_transform_exclusive_scan(KE::cbegin(data_view_h),
|
||||||
|
KE::cend(data_view_h), KE::begin(gold_h),
|
||||||
|
init_value, bop, uop);
|
||||||
|
|
||||||
|
auto test_view_dc = create_deep_copyable_compatible_clone(test_view);
|
||||||
|
auto test_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), test_view_dc);
|
||||||
|
if (test_view_h.extent(0) > 0) {
|
||||||
|
for (std::size_t i = 0; i < test_view_h.extent(0); ++i) {
|
||||||
|
// std::cout << i << " " << std::setprecision(15) << data_view_h(i) << " "
|
||||||
|
// << gold_h(i) << " " << test_view_h(i) << " "
|
||||||
|
// << std::abs(gold_h(i) - test_view_h(i)) << std::endl;
|
||||||
|
|
||||||
|
if (std::is_same<gold_view_value_type, int>::value) {
|
||||||
|
EXPECT_TRUE(gold_h(i) == test_view_h(i));
|
||||||
|
} else {
|
||||||
|
const auto error = std::abs(gold_h(i) - test_view_h(i));
|
||||||
|
if (error > 1e-10) {
|
||||||
|
std::cout << i << " " << std::setprecision(15) << data_view_h(i)
|
||||||
|
<< " " << gold_h(i) << " " << test_view_h(i) << " "
|
||||||
|
<< std::abs(gold_h(i) - test_view_h(i)) << std::endl;
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(error < 1e-10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// std::cout << " last el: " << test_view_h(test_view_h.extent(0)-1) <<
|
||||||
|
// std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TimesTwoUnaryFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a) const { return (a * ValueType(2)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct SumBinaryFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const volatile ValueType& a,
|
||||||
|
const volatile ValueType& b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class BinaryOp,
|
||||||
|
class UnaryOp>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info, ValueType init_value,
|
||||||
|
BinaryOp bop, UnaryOp uop) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "transform_exclusive_scan custom op: " << name << ", "
|
||||||
|
// << view_tag_to_string(Tag{}) << ", "
|
||||||
|
// << value_type_to_string(ValueType()) << ", "
|
||||||
|
// << "init = " << init_value << std::endl;
|
||||||
|
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "transform_exclusive_scan");
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "transform_exclusive_scan");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::transform_exclusive_scan(
|
||||||
|
exespace(), KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), init_value, bop, uop);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, bop, uop);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::transform_exclusive_scan(
|
||||||
|
"label", exespace(), KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), init_value, bop, uop);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, bop, uop);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::transform_exclusive_scan(exespace(), view_from, view_dest,
|
||||||
|
init_value, bop, uop);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, bop, uop);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::transform_exclusive_scan("label", exespace(), view_from,
|
||||||
|
view_dest, init_value, bop, uop);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, init_value, bop, uop);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element", 1}, {"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2}, {"small-a", 9}, {"small-b", 13},
|
||||||
|
{"medium", 1103}, {"large", 10513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
using uop_t = TimesTwoUnaryFunctor<ValueType>;
|
||||||
|
using bop_t = SumBinaryFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, ValueType{0}, bop_t(), uop_t());
|
||||||
|
run_single_scenario<Tag, ValueType>(it, ValueType{1}, bop_t(), uop_t());
|
||||||
|
run_single_scenario<Tag, ValueType>(it, ValueType{-2}, bop_t(), uop_t());
|
||||||
|
run_single_scenario<Tag, ValueType>(it, ValueType{3}, bop_t(), uop_t());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
TEST(std_algorithms_numeric_ops_test, transform_exclusive_scan) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace TransformEScan
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,347 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_Numeric.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace TransformIncScan {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<double> {
|
||||||
|
using dist_type = std::uniform_real_distribution<double>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(0.05, 1.2) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
double operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(1, 3) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_zero(ViewType view) {
|
||||||
|
Kokkos::parallel_for(view.extent(0), FillZeroFunctor<ViewType>(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element") {
|
||||||
|
assert(v_h.extent(0) == 1);
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
assert(v_h.extent(0) == 2);
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
assert(v_h.extent(0) == 2);
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
assert(v_h.extent(0) == 9);
|
||||||
|
v_h(0) = static_cast<value_type>(3);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(4);
|
||||||
|
v_h(3) = static_cast<value_type>(1);
|
||||||
|
v_h(4) = static_cast<value_type>(5);
|
||||||
|
v_h(5) = static_cast<value_type>(9);
|
||||||
|
v_h(6) = static_cast<value_type>(2);
|
||||||
|
v_h(7) = static_cast<value_type>(6);
|
||||||
|
v_h(8) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
assert(v_h.extent(0) >= 6);
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
v_h(5) = static_cast<value_type>(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// I had to write my own because std::transform_inclusive_scan is ONLY found
|
||||||
|
// with std=c++17
|
||||||
|
template <class it1, class it2, class BopType, class UopType>
|
||||||
|
void my_host_transform_inclusive_scan(it1 first, it1 last, it2 dest,
|
||||||
|
BopType bop, UopType uop) {
|
||||||
|
if (first != last) {
|
||||||
|
auto init = uop(*first);
|
||||||
|
*dest = init;
|
||||||
|
while (++first < last) {
|
||||||
|
init = bop(uop(*first), init);
|
||||||
|
*(++dest) = init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class it1, class it2, class ValType, class BopType, class UopType>
|
||||||
|
void my_host_transform_inclusive_scan(it1 first, it1 last, it2 dest,
|
||||||
|
BopType bop, UopType uop, ValType init) {
|
||||||
|
if (first != last) {
|
||||||
|
init = bop(uop(*first), init);
|
||||||
|
*dest = init;
|
||||||
|
while (++first < last) {
|
||||||
|
init = bop(uop(*first), init);
|
||||||
|
*(++dest) = init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewType1, class ViewType2, class... Args>
|
||||||
|
void verify_data(ViewType1 data_view, // contains data
|
||||||
|
ViewType2 test_view, // the view to test
|
||||||
|
Args... args /* by value on purpose*/) {
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
|
||||||
|
auto data_view_dc = create_deep_copyable_compatible_clone(data_view);
|
||||||
|
auto data_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), data_view_dc);
|
||||||
|
|
||||||
|
using gold_view_value_type = typename ViewType2::value_type;
|
||||||
|
Kokkos::View<gold_view_value_type*, Kokkos::HostSpace> gold_h(
|
||||||
|
"goldh", data_view.extent(0));
|
||||||
|
my_host_transform_inclusive_scan(KE::cbegin(data_view_h),
|
||||||
|
KE::cend(data_view_h), KE::begin(gold_h),
|
||||||
|
args...);
|
||||||
|
|
||||||
|
auto test_view_dc = create_deep_copyable_compatible_clone(test_view);
|
||||||
|
auto test_view_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), test_view_dc);
|
||||||
|
if (test_view_h.extent(0) > 0) {
|
||||||
|
for (std::size_t i = 0; i < test_view_h.extent(0); ++i) {
|
||||||
|
// std::cout << i << " " << std::setprecision(15) << data_view_h(i) << " "
|
||||||
|
// << gold_h(i) << " " << test_view_h(i) << " "
|
||||||
|
// << std::abs(gold_h(i) - test_view_h(i)) << std::endl;
|
||||||
|
|
||||||
|
if (std::is_same<gold_view_value_type, int>::value) {
|
||||||
|
EXPECT_TRUE(gold_h(i) == test_view_h(i));
|
||||||
|
} else {
|
||||||
|
const auto error = std::abs(gold_h(i) - test_view_h(i));
|
||||||
|
if (error > 1e-10) {
|
||||||
|
std::cout << i << " " << std::setprecision(15) << data_view_h(i)
|
||||||
|
<< " " << gold_h(i) << " " << test_view_h(i) << " "
|
||||||
|
<< std::abs(gold_h(i) - test_view_h(i)) << std::endl;
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(error < 1e-10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// std::cout << " last el: " << test_view_h(test_view_h.extent(0)-1) <<
|
||||||
|
// std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TimesTwoUnaryFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a) const { return (a * ValueType(2)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct SumBinaryFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& a, const ValueType& b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const volatile ValueType& a,
|
||||||
|
const volatile ValueType& b) const {
|
||||||
|
return (a + b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class BopT, class UopT>
|
||||||
|
void print_scenario_details(const std::string& name, BopT bop, UopT uop) {
|
||||||
|
(void)bop;
|
||||||
|
(void)uop;
|
||||||
|
std::cout << "transform_inclusive_scan: " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class BopT, class UopT, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name, BopT bop, UopT uop,
|
||||||
|
ValueType init_value) {
|
||||||
|
(void)bop;
|
||||||
|
(void)uop;
|
||||||
|
std::cout << "transform_inclusive_scan: " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << ", "
|
||||||
|
<< "init = " << init_value << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class... Args>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info,
|
||||||
|
Args... args /* by value on purpose*/) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag>(name, args...);
|
||||||
|
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "transform_inclusive_scan");
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "transform_inclusive_scan");
|
||||||
|
fill_view(view_from, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::transform_inclusive_scan(exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), args...);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::transform_inclusive_scan(
|
||||||
|
"label", exespace(), KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), args...);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r =
|
||||||
|
KE::transform_inclusive_scan(exespace(), view_from, view_dest, args...);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_zero(view_dest);
|
||||||
|
auto r = KE::transform_inclusive_scan("label", exespace(), view_from,
|
||||||
|
view_dest, args...);
|
||||||
|
EXPECT_TRUE(r == KE::end(view_dest));
|
||||||
|
verify_data(view_from, view_dest, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element", 1}, {"two-elements-a", 2},
|
||||||
|
{"two-elements-b", 2}, {"small-a", 9}, {"small-b", 13},
|
||||||
|
{"medium", 1103}, {"large", 10513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
using uop_t = TimesTwoUnaryFunctor<ValueType>;
|
||||||
|
using bop_t = SumBinaryFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, bop_t(), uop_t());
|
||||||
|
run_single_scenario<Tag, ValueType>(it, bop_t(), uop_t(), ValueType{0});
|
||||||
|
run_single_scenario<Tag, ValueType>(it, bop_t(), uop_t(), ValueType{1});
|
||||||
|
run_single_scenario<Tag, ValueType>(it, bop_t(), uop_t(), ValueType{2});
|
||||||
|
run_single_scenario<Tag, ValueType>(it, bop_t(), uop_t(), ValueType{-1});
|
||||||
|
run_single_scenario<Tag, ValueType>(it, bop_t(), uop_t(), ValueType{-2});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if not defined KOKKOS_ENABLE_OPENMPTARGET
|
||||||
|
TEST(std_algorithms_numeric_ops_test, transform_inclusive_scan) {
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
// run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
// run_all_scenarios<DynamicTag, int>();
|
||||||
|
// run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace TransformIncScan
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace TransformUnaryOp {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeFrom, class ViewTypeTest>
|
||||||
|
void verify_data(ViewTypeFrom view_from, ViewTypeTest view_test) {
|
||||||
|
using value_type = typename ViewTypeFrom::value_type;
|
||||||
|
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
auto view_test_dc = create_deep_copyable_compatible_clone(view_test);
|
||||||
|
auto view_test_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_test_dc);
|
||||||
|
|
||||||
|
auto view_from_dc = create_deep_copyable_compatible_clone(view_from);
|
||||||
|
auto view_from_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_from_dc);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < view_test_h.extent(0); ++i) {
|
||||||
|
EXPECT_TRUE(view_test_h(i) == view_from_h(i) + value_type(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct TransformFunctor {
|
||||||
|
KOKKOS_INLINE_FUNCTION
|
||||||
|
ValueType operator()(const ValueType& val) const {
|
||||||
|
return val + ValueType(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// std::cout << "transform_unary_op: " << name << ", "
|
||||||
|
// << view_tag_to_string(Tag{}) << ", "
|
||||||
|
// << value_type_to_string(ValueType()) << std::endl;
|
||||||
|
|
||||||
|
auto view_from =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "transform_uop_from");
|
||||||
|
fill_view(view_from);
|
||||||
|
TransformFunctor<ValueType> unOp;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "transform_uop_dest");
|
||||||
|
auto r1 = KE::transform(exespace(), KE::begin(view_from),
|
||||||
|
KE::end(view_from), KE::begin(view_dest), unOp);
|
||||||
|
verify_data(view_from, view_dest);
|
||||||
|
EXPECT_EQ(r1, KE::end(view_dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "transform_uop_dest");
|
||||||
|
auto r1 = KE::transform("label", exespace(), KE::begin(view_from),
|
||||||
|
KE::end(view_from), KE::begin(view_dest), unOp);
|
||||||
|
verify_data(view_from, view_dest);
|
||||||
|
EXPECT_EQ(r1, KE::end(view_dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "transform_uop_dest");
|
||||||
|
auto r1 = KE::transform(exespace(), view_from, view_dest, unOp);
|
||||||
|
verify_data(view_from, view_dest);
|
||||||
|
EXPECT_EQ(r1, KE::end(view_dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "transform_uop_dest");
|
||||||
|
auto r1 = KE::transform("label", exespace(), view_from, view_dest, unOp);
|
||||||
|
verify_data(view_from, view_dest);
|
||||||
|
EXPECT_EQ(r1, KE::end(view_dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 9},
|
||||||
|
{"small-b", 13}, {"medium", 1103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_transform_ops_test, transform_unary_op) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
run_all_scenarios<DynamicTag, double>();
|
||||||
|
run_all_scenarios<StridedThreeTag, double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace TransformUnaryOp
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
312
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsUnique.cpp
Normal file
312
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsUnique.cpp
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace Unique {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(2, 7) { m_gen.seed(1034343); }
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
void fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(0);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(3);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(2);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(4);
|
||||||
|
v_h(7) = static_cast<value_type>(4);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(6);
|
||||||
|
v_h(10) = static_cast<value_type>(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(3);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(4);
|
||||||
|
v_h(7) = static_cast<value_type>(4);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(6);
|
||||||
|
v_h(10) = static_cast<value_type>(8);
|
||||||
|
v_h(11) = static_cast<value_type>(9);
|
||||||
|
v_h(12) = static_cast<value_type>(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium-a") {
|
||||||
|
// beginning just contains increasing values
|
||||||
|
for (std::size_t i = 0; i < 1000; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then use random
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 1000; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium-b") {
|
||||||
|
for (std::size_t i = 0; i < 1000; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(22);
|
||||||
|
}
|
||||||
|
for (std::size_t i = 1000; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(44);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-a") {
|
||||||
|
// put equal elements at the end
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = static_cast<value_type>(i);
|
||||||
|
}
|
||||||
|
v_h(ext - 3) = static_cast<value_type>(44);
|
||||||
|
v_h(ext - 2) = static_cast<value_type>(44);
|
||||||
|
v_h(ext - 1) = static_cast<value_type>(44);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "large-b") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ResultIt, class ViewType1, class ViewType2, class... Args>
|
||||||
|
void verify_data(const std::string& name, ResultIt my_result_it,
|
||||||
|
ViewType1 view_test, ViewType2 data_v_h, Args... args) {
|
||||||
|
// run std unique on host data
|
||||||
|
auto std_r = std::unique(KE::begin(data_v_h), KE::end(data_v_h), args...);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check the returned iterator is correct
|
||||||
|
//
|
||||||
|
const auto std_diff = (std::size_t)(std_r - KE::begin(data_v_h));
|
||||||
|
const auto my_diff = (std::size_t)(my_result_it - KE::begin(view_test));
|
||||||
|
EXPECT_TRUE(my_diff == std_diff);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check the data in the view
|
||||||
|
//
|
||||||
|
// Note that we need to stop after std_diff because
|
||||||
|
// after that values are unspecified, see std::unique
|
||||||
|
auto view_test_h = create_host_space_copy(view_test);
|
||||||
|
for (std::size_t i = 0; i < std_diff; ++i) {
|
||||||
|
// std::cout << "i = " << i
|
||||||
|
// << " my = " << view_test_h(i) << " "
|
||||||
|
// << " std = " << data_v_h(i)
|
||||||
|
// << '\n';
|
||||||
|
EXPECT_TRUE(view_test_h(i) == data_v_h(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == "medium-b") {
|
||||||
|
using value_type = typename ViewType1::value_type;
|
||||||
|
EXPECT_TRUE(my_diff == (std::size_t)2);
|
||||||
|
EXPECT_TRUE(view_test_h(0) == (value_type)22);
|
||||||
|
EXPECT_TRUE(view_test_h(1) == (value_type)44);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name) {
|
||||||
|
std::cout << "unique: default predicate: " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class Predicate>
|
||||||
|
void print_scenario_details(const std::string& name, Predicate pred) {
|
||||||
|
(void)pred;
|
||||||
|
std::cout << "unique: custom predicate: " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class... Args>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info, Args... args) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, args...);
|
||||||
|
|
||||||
|
auto test_view = create_view<ValueType>(Tag{}, view_ext, "unique_test_view");
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(test_view, name);
|
||||||
|
// make host copy BEFORE running unique on it since unique modifies it
|
||||||
|
auto data_h = create_host_space_copy(test_view);
|
||||||
|
|
||||||
|
// run unique
|
||||||
|
auto rit = KE::unique(exespace(), KE::begin(test_view), KE::end(test_view),
|
||||||
|
args...);
|
||||||
|
// verify
|
||||||
|
verify_data(name, rit, test_view, data_h, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(test_view, name);
|
||||||
|
// make host copy BEFORE running unique on it since unique modifies it
|
||||||
|
auto data_h = create_host_space_copy(test_view);
|
||||||
|
|
||||||
|
// run unique
|
||||||
|
auto rit = KE::unique("label", exespace(), KE::begin(test_view),
|
||||||
|
KE::end(test_view), args...);
|
||||||
|
// verify
|
||||||
|
verify_data(name, rit, test_view, data_h, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(test_view, name);
|
||||||
|
// make host copy BEFORE running unique on it since unique modifies it
|
||||||
|
auto data_h = create_host_space_copy(test_view);
|
||||||
|
|
||||||
|
// run unique
|
||||||
|
auto rit = KE::unique(exespace(), test_view, args...);
|
||||||
|
// verify
|
||||||
|
verify_data(name, rit, test_view, data_h, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fill_view(test_view, name);
|
||||||
|
// make host copy BEFORE running unique on it since unique modifies it
|
||||||
|
auto data_h = create_host_space_copy(test_view);
|
||||||
|
|
||||||
|
// run unique
|
||||||
|
auto rit = KE::unique("label", exespace(), test_view, args...);
|
||||||
|
// verify
|
||||||
|
verify_data(name, rit, test_view, data_h, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 11},
|
||||||
|
{"small-b", 13}, {"medium-a", 11103}, {"medium-b", 21103},
|
||||||
|
{"large-a", 101513}, {"large-b", 100111}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
|
||||||
|
using func_t = IsEqualFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, func_t());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, unique) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Unique
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
361
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsUniqueCopy.cpp
Normal file
361
lib/kokkos/algorithms/unit_tests/TestStdAlgorithmsUniqueCopy.cpp
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <TestStdAlgorithmsCommon.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_BeginEnd.hpp>
|
||||||
|
#include <std_algorithms/Kokkos_ModifyingSequenceOperations.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
namespace stdalgos {
|
||||||
|
namespace UniqueCopy {
|
||||||
|
|
||||||
|
namespace KE = Kokkos::Experimental;
|
||||||
|
|
||||||
|
// impl is here for std because it is only avail from c++>=17
|
||||||
|
template <class InputIterator, class OutputIterator, class BinaryPredicate>
|
||||||
|
auto my_unique_copy(InputIterator first, InputIterator last,
|
||||||
|
OutputIterator result, BinaryPredicate pred) {
|
||||||
|
if (first != last) {
|
||||||
|
typename OutputIterator::value_type t(*first);
|
||||||
|
*result = t;
|
||||||
|
++result;
|
||||||
|
while (++first != last) {
|
||||||
|
if (!pred(t, *first)) {
|
||||||
|
t = *first;
|
||||||
|
*result = t;
|
||||||
|
++result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class InputIterator, class OutputIterator>
|
||||||
|
auto my_unique_copy(InputIterator first, InputIterator last,
|
||||||
|
OutputIterator result) {
|
||||||
|
using value_type = typename OutputIterator::value_type;
|
||||||
|
using func_t = IsEqualFunctor<value_type>;
|
||||||
|
return my_unique_copy(first, last, result, func_t());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ValueType>
|
||||||
|
struct UnifDist;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct UnifDist<int> {
|
||||||
|
using dist_type = std::uniform_int_distribution<int>;
|
||||||
|
std::mt19937 m_gen;
|
||||||
|
dist_type m_dist;
|
||||||
|
|
||||||
|
UnifDist() : m_dist(2, 7) { m_gen.seed(1034343); }
|
||||||
|
|
||||||
|
int operator()() { return m_dist(m_gen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ViewType>
|
||||||
|
std::size_t fill_view(ViewType dest_view, const std::string& name) {
|
||||||
|
using value_type = typename ViewType::value_type;
|
||||||
|
using exe_space = typename ViewType::execution_space;
|
||||||
|
const std::size_t ext = dest_view.extent(0);
|
||||||
|
using aux_view_t = Kokkos::View<value_type*, exe_space>;
|
||||||
|
aux_view_t aux_view("aux_view", ext);
|
||||||
|
auto v_h = create_mirror_view(Kokkos::HostSpace(), aux_view);
|
||||||
|
|
||||||
|
std::size_t count = 0;
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(2);
|
||||||
|
count = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(2);
|
||||||
|
v_h(1) = static_cast<value_type>(-1);
|
||||||
|
count = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
v_h(0) = static_cast<value_type>(0);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(3);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(4);
|
||||||
|
v_h(7) = static_cast<value_type>(4);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(6);
|
||||||
|
v_h(10) = static_cast<value_type>(6);
|
||||||
|
count = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
v_h(0) = static_cast<value_type>(1);
|
||||||
|
v_h(1) = static_cast<value_type>(1);
|
||||||
|
v_h(2) = static_cast<value_type>(1);
|
||||||
|
v_h(3) = static_cast<value_type>(2);
|
||||||
|
v_h(4) = static_cast<value_type>(3);
|
||||||
|
v_h(5) = static_cast<value_type>(4);
|
||||||
|
v_h(6) = static_cast<value_type>(4);
|
||||||
|
v_h(7) = static_cast<value_type>(4);
|
||||||
|
v_h(8) = static_cast<value_type>(5);
|
||||||
|
v_h(9) = static_cast<value_type>(6);
|
||||||
|
v_h(10) = static_cast<value_type>(8);
|
||||||
|
v_h(11) = static_cast<value_type>(9);
|
||||||
|
v_h(12) = static_cast<value_type>(8);
|
||||||
|
count = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
UnifDist<value_type> randObj;
|
||||||
|
for (std::size_t i = 0; i < ext; ++i) {
|
||||||
|
v_h(i) = randObj();
|
||||||
|
}
|
||||||
|
std::vector<value_type> tmp(v_h.extent(0));
|
||||||
|
std::fill(tmp.begin(), tmp.end(), static_cast<value_type>(0));
|
||||||
|
using func_t = IsEqualFunctor<value_type>;
|
||||||
|
auto std_r =
|
||||||
|
my_unique_copy(KE::cbegin(v_h), KE::cend(v_h), tmp.begin(), func_t());
|
||||||
|
count = (std::size_t)(std_r - tmp.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::deep_copy(aux_view, v_h);
|
||||||
|
CopyFunctor<aux_view_t, ViewType> F1(aux_view, dest_view);
|
||||||
|
Kokkos::parallel_for("copy", dest_view.extent(0), F1);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ViewTypeFrom, class ViewTypeTest, class... Args>
|
||||||
|
void verify_data(const std::string& name, ViewTypeFrom view_from,
|
||||||
|
ViewTypeTest view_test, Args... args) {
|
||||||
|
using value_type = typename ViewTypeTest::value_type;
|
||||||
|
|
||||||
|
//! always careful because views might not be deep copyable
|
||||||
|
auto view_test_dc = create_deep_copyable_compatible_clone(view_test);
|
||||||
|
auto view_test_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_test_dc);
|
||||||
|
|
||||||
|
auto view_from_dc = create_deep_copyable_compatible_clone(view_from);
|
||||||
|
auto view_from_h =
|
||||||
|
create_mirror_view_and_copy(Kokkos::HostSpace(), view_from_dc);
|
||||||
|
|
||||||
|
if (name == "empty") {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-a") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "one-element-b") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-a") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(1));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == static_cast<value_type>(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "two-elements-b") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(2));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == static_cast<value_type>(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-a") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == static_cast<value_type>(1));
|
||||||
|
EXPECT_TRUE(view_test_h(2) == static_cast<value_type>(2));
|
||||||
|
EXPECT_TRUE(view_test_h(3) == static_cast<value_type>(3));
|
||||||
|
EXPECT_TRUE(view_test_h(4) == static_cast<value_type>(4));
|
||||||
|
EXPECT_TRUE(view_test_h(5) == static_cast<value_type>(5));
|
||||||
|
EXPECT_TRUE(view_test_h(6) == static_cast<value_type>(6));
|
||||||
|
EXPECT_TRUE(view_test_h(7) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(8) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(9) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(10) == static_cast<value_type>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "small-b") {
|
||||||
|
EXPECT_TRUE(view_test_h(0) == static_cast<value_type>(1));
|
||||||
|
EXPECT_TRUE(view_test_h(1) == static_cast<value_type>(2));
|
||||||
|
EXPECT_TRUE(view_test_h(2) == static_cast<value_type>(3));
|
||||||
|
EXPECT_TRUE(view_test_h(3) == static_cast<value_type>(4));
|
||||||
|
EXPECT_TRUE(view_test_h(4) == static_cast<value_type>(5));
|
||||||
|
EXPECT_TRUE(view_test_h(5) == static_cast<value_type>(6));
|
||||||
|
EXPECT_TRUE(view_test_h(6) == static_cast<value_type>(8));
|
||||||
|
EXPECT_TRUE(view_test_h(7) == static_cast<value_type>(9));
|
||||||
|
EXPECT_TRUE(view_test_h(8) == static_cast<value_type>(8));
|
||||||
|
EXPECT_TRUE(view_test_h(9) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(10) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(11) == static_cast<value_type>(0));
|
||||||
|
EXPECT_TRUE(view_test_h(12) == static_cast<value_type>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "medium" || name == "large") {
|
||||||
|
std::vector<value_type> tmp(view_test_h.extent(0));
|
||||||
|
std::fill(tmp.begin(), tmp.end(), static_cast<value_type>(0));
|
||||||
|
|
||||||
|
auto std_r = my_unique_copy(KE::cbegin(view_from_h), KE::cend(view_from_h),
|
||||||
|
tmp.begin(), args...);
|
||||||
|
(void)std_r;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < view_from_h.extent(0); ++i) {
|
||||||
|
EXPECT_TRUE(view_test_h(i) == tmp[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("invalid choice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value_type_to_string(int) { return "int"; }
|
||||||
|
std::string value_type_to_string(double) { return "double"; }
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void print_scenario_details(const std::string& name) {
|
||||||
|
std::cout << "unique_copy: default predicate: " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class Predicate>
|
||||||
|
void print_scenario_details(const std::string& name, Predicate pred) {
|
||||||
|
(void)pred;
|
||||||
|
std::cout << "unique_copy: custom predicate: " << name << ", "
|
||||||
|
<< view_tag_to_string(Tag{}) << " "
|
||||||
|
<< value_type_to_string(ValueType()) << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType, class InfoType, class... Args>
|
||||||
|
void run_single_scenario(const InfoType& scenario_info, Args... args) {
|
||||||
|
const auto name = std::get<0>(scenario_info);
|
||||||
|
const std::size_t view_ext = std::get<1>(scenario_info);
|
||||||
|
// print_scenario_details<Tag, ValueType>(name, args...);
|
||||||
|
|
||||||
|
auto view_from = create_view<ValueType>(Tag{}, view_ext, "unique_copy_from");
|
||||||
|
auto n = fill_view(view_from, name);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "unique_copy_dest");
|
||||||
|
auto rit =
|
||||||
|
KE::unique_copy(exespace(), KE::cbegin(view_from), KE::cend(view_from),
|
||||||
|
KE::begin(view_dest), args...);
|
||||||
|
verify_data(name, view_from, view_dest, args...);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + n));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "unique_copy_dest");
|
||||||
|
auto rit =
|
||||||
|
KE::unique_copy("label", exespace(), KE::cbegin(view_from),
|
||||||
|
KE::cend(view_from), KE::begin(view_dest), args...);
|
||||||
|
verify_data(name, view_from, view_dest, args...);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + n));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "unique_copy_dest");
|
||||||
|
auto rit = KE::unique_copy(exespace(), view_from, view_dest, args...);
|
||||||
|
verify_data(name, view_from, view_dest, args...);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + n));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto view_dest =
|
||||||
|
create_view<ValueType>(Tag{}, view_ext, "unique_copy_dest");
|
||||||
|
auto rit =
|
||||||
|
KE::unique_copy("label", exespace(), view_from, view_dest, args...);
|
||||||
|
verify_data(name, view_from, view_dest, args...);
|
||||||
|
EXPECT_TRUE(rit == (KE::begin(view_dest) + n));
|
||||||
|
}
|
||||||
|
|
||||||
|
Kokkos::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Tag, class ValueType>
|
||||||
|
void run_all_scenarios() {
|
||||||
|
const std::map<std::string, std::size_t> scenarios = {
|
||||||
|
{"empty", 0}, {"one-element-a", 1}, {"one-element-b", 1},
|
||||||
|
{"two-elements-a", 2}, {"two-elements-b", 2}, {"small-a", 11},
|
||||||
|
{"small-b", 13}, {"medium", 21103}, {"large", 101513}};
|
||||||
|
|
||||||
|
for (const auto& it : scenarios) {
|
||||||
|
run_single_scenario<Tag, ValueType>(it);
|
||||||
|
|
||||||
|
using func_t = IsEqualFunctor<ValueType>;
|
||||||
|
run_single_scenario<Tag, ValueType>(it, func_t());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_mod_seq_ops, unique_copy) {
|
||||||
|
run_all_scenarios<DynamicTag, int>();
|
||||||
|
run_all_scenarios<StridedThreeTag, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace UniqueCopy
|
||||||
|
} // namespace stdalgos
|
||||||
|
} // namespace Test
|
||||||
281
lib/kokkos/algorithms/unit_tests/TestStdReducers.cpp
Normal file
281
lib/kokkos/algorithms/unit_tests/TestStdReducers.cpp
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Kokkos_Core.hpp>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
// purpose of this test is to check that the reducers used
|
||||||
|
// to implement some std algorithms work independently of the order
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
|
||||||
|
enum class StdReducersTestEnumOrder { LeftToRight, RightToLeft, Random };
|
||||||
|
|
||||||
|
std::string order_to_string(StdReducersTestEnumOrder value) {
|
||||||
|
switch (value) {
|
||||||
|
case StdReducersTestEnumOrder::LeftToRight: return "LeftToRight";
|
||||||
|
case StdReducersTestEnumOrder::RightToLeft: return "RightToLeft";
|
||||||
|
case StdReducersTestEnumOrder::Random: return "Random";
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto create_host_view_with_reduction_order_indices(
|
||||||
|
std::size_t extent, StdReducersTestEnumOrder enum_value) {
|
||||||
|
using view_t = Kokkos::View<int*, Kokkos::HostSpace>;
|
||||||
|
view_t result("v", extent);
|
||||||
|
|
||||||
|
if (enum_value == StdReducersTestEnumOrder::LeftToRight) {
|
||||||
|
result(0) = 0;
|
||||||
|
result(1) = 1;
|
||||||
|
result(2) = 2;
|
||||||
|
result(3) = 3;
|
||||||
|
result(4) = 4;
|
||||||
|
result(5) = 5;
|
||||||
|
result(6) = 6;
|
||||||
|
result(7) = 7;
|
||||||
|
result(8) = 8;
|
||||||
|
result(9) = 9;
|
||||||
|
} else if (enum_value == StdReducersTestEnumOrder::RightToLeft) {
|
||||||
|
result(0) = 9;
|
||||||
|
result(1) = 8;
|
||||||
|
result(2) = 7;
|
||||||
|
result(3) = 6;
|
||||||
|
result(4) = 5;
|
||||||
|
result(5) = 4;
|
||||||
|
result(6) = 3;
|
||||||
|
result(7) = 2;
|
||||||
|
result(8) = 1;
|
||||||
|
result(9) = 0;
|
||||||
|
} else if (enum_value == StdReducersTestEnumOrder::Random) {
|
||||||
|
result(0) = 0;
|
||||||
|
result(1) = 8;
|
||||||
|
result(2) = 3;
|
||||||
|
result(3) = 2;
|
||||||
|
result(4) = 9;
|
||||||
|
result(5) = 4;
|
||||||
|
result(6) = 6;
|
||||||
|
result(7) = 1;
|
||||||
|
result(8) = 7;
|
||||||
|
result(9) = 5;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("test: Invalid enum");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int flag, class ExeSpace, class IndexType, class ViewType>
|
||||||
|
auto run_min_or_max_test(ViewType view, StdReducersTestEnumOrder enValue) {
|
||||||
|
static_assert(std::is_same<ExeSpace, Kokkos::HostSpace>::value,
|
||||||
|
"test is only enabled for HostSpace");
|
||||||
|
|
||||||
|
std::cout << "checking reduction with order: " << order_to_string(enValue)
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
using view_value_type = typename ViewType::value_type;
|
||||||
|
using reducer_type = typename std::conditional<
|
||||||
|
(flag == 0), Kokkos::MaxFirstLoc<view_value_type, IndexType, ExeSpace>,
|
||||||
|
Kokkos::MinFirstLoc<view_value_type, IndexType, ExeSpace> >::type;
|
||||||
|
using reduction_value_type = typename reducer_type::value_type;
|
||||||
|
|
||||||
|
reduction_value_type red_result;
|
||||||
|
reducer_type reducer(red_result);
|
||||||
|
EXPECT_TRUE(reducer.references_scalar());
|
||||||
|
reducer.init(red_result);
|
||||||
|
|
||||||
|
auto red_order =
|
||||||
|
create_host_view_with_reduction_order_indices(view.extent(0), enValue);
|
||||||
|
for (std::size_t i = 0; i < view.extent(0); ++i) {
|
||||||
|
const auto index = red_order(i);
|
||||||
|
reducer.join(red_result, reduction_value_type{view(index), index});
|
||||||
|
}
|
||||||
|
|
||||||
|
using return_type = Kokkos::pair<view_value_type, IndexType>;
|
||||||
|
return return_type{red_result.val, red_result.loc};
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_reducers, max_first_loc) {
|
||||||
|
using hostspace = Kokkos::HostSpace;
|
||||||
|
|
||||||
|
using view_t = Kokkos::View<double*, hostspace>;
|
||||||
|
constexpr std::size_t extent = 10;
|
||||||
|
view_t view_h("v", extent);
|
||||||
|
view_h(0) = 0.;
|
||||||
|
view_h(1) = 0.;
|
||||||
|
view_h(2) = 0.;
|
||||||
|
view_h(3) = 2.;
|
||||||
|
view_h(4) = 2.;
|
||||||
|
view_h(5) = 1.;
|
||||||
|
view_h(6) = 1.;
|
||||||
|
view_h(7) = 1.;
|
||||||
|
view_h(8) = 1.;
|
||||||
|
view_h(9) = 0.;
|
||||||
|
|
||||||
|
using index_type = int;
|
||||||
|
using view_value_type = typename view_t::value_type;
|
||||||
|
const view_value_type gold_value = 2.;
|
||||||
|
const index_type gold_location = 3;
|
||||||
|
|
||||||
|
const auto pair1 = run_min_or_max_test<0, hostspace, index_type>(
|
||||||
|
view_h, StdReducersTestEnumOrder::LeftToRight);
|
||||||
|
ASSERT_EQ(pair1.first, gold_value);
|
||||||
|
ASSERT_EQ(pair1.second, gold_location);
|
||||||
|
|
||||||
|
const auto pair2 = run_min_or_max_test<0, hostspace, index_type>(
|
||||||
|
view_h, StdReducersTestEnumOrder::RightToLeft);
|
||||||
|
ASSERT_EQ(pair2.first, gold_value);
|
||||||
|
ASSERT_EQ(pair2.second, gold_location);
|
||||||
|
|
||||||
|
const auto pair3 = run_min_or_max_test<0, hostspace, index_type>(
|
||||||
|
view_h, StdReducersTestEnumOrder::Random);
|
||||||
|
ASSERT_EQ(pair3.first, gold_value);
|
||||||
|
ASSERT_EQ(pair3.second, gold_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_reducers, min_first_loc) {
|
||||||
|
using hostspace = Kokkos::HostSpace;
|
||||||
|
|
||||||
|
using view_t = Kokkos::View<double*, hostspace>;
|
||||||
|
constexpr std::size_t extent = 10;
|
||||||
|
view_t view_h("v", extent);
|
||||||
|
view_h(0) = 0.;
|
||||||
|
view_h(1) = 0.;
|
||||||
|
view_h(2) = 0.;
|
||||||
|
view_h(3) = 2.;
|
||||||
|
view_h(4) = 2.;
|
||||||
|
view_h(5) = -1.;
|
||||||
|
view_h(6) = -1.;
|
||||||
|
view_h(7) = 1.;
|
||||||
|
view_h(8) = 1.;
|
||||||
|
view_h(9) = 0.;
|
||||||
|
|
||||||
|
using index_type = int;
|
||||||
|
using view_value_type = typename view_t::value_type;
|
||||||
|
const view_value_type gold_value = -1.;
|
||||||
|
const index_type gold_location = 5;
|
||||||
|
|
||||||
|
const auto pair1 = run_min_or_max_test<1, hostspace, index_type>(
|
||||||
|
view_h, StdReducersTestEnumOrder::LeftToRight);
|
||||||
|
ASSERT_EQ(pair1.first, gold_value);
|
||||||
|
ASSERT_EQ(pair1.second, gold_location);
|
||||||
|
|
||||||
|
const auto pair2 = run_min_or_max_test<1, hostspace, index_type>(
|
||||||
|
view_h, StdReducersTestEnumOrder::RightToLeft);
|
||||||
|
ASSERT_EQ(pair2.first, gold_value);
|
||||||
|
ASSERT_EQ(pair2.second, gold_location);
|
||||||
|
|
||||||
|
const auto pair3 = run_min_or_max_test<1, hostspace, index_type>(
|
||||||
|
view_h, StdReducersTestEnumOrder::Random);
|
||||||
|
ASSERT_EQ(pair3.first, gold_value);
|
||||||
|
ASSERT_EQ(pair3.second, gold_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ExeSpace, class IndexType, class ViewType, class ValuesPair,
|
||||||
|
class IndexPair>
|
||||||
|
void run_min_max_test(ViewType view, StdReducersTestEnumOrder enValue,
|
||||||
|
const ValuesPair gold_values, const IndexPair gold_locs) {
|
||||||
|
static_assert(std::is_same<ExeSpace, Kokkos::HostSpace>::value,
|
||||||
|
"test is only enabled for HostSpace");
|
||||||
|
|
||||||
|
std::cout << "checking reduction with order: " << order_to_string(enValue)
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
using view_value_type = typename ViewType::value_type;
|
||||||
|
using reducer_type =
|
||||||
|
Kokkos::MinMaxFirstLastLoc<view_value_type, IndexType, ExeSpace>;
|
||||||
|
using reduction_value_type = typename reducer_type::value_type;
|
||||||
|
|
||||||
|
reduction_value_type red_result;
|
||||||
|
reducer_type reducer(red_result);
|
||||||
|
EXPECT_TRUE(reducer.references_scalar());
|
||||||
|
reducer.init(red_result);
|
||||||
|
|
||||||
|
auto red_order =
|
||||||
|
create_host_view_with_reduction_order_indices(view.extent(0), enValue);
|
||||||
|
for (std::size_t i = 0; i < view.extent(0); ++i) {
|
||||||
|
const auto index = red_order(i);
|
||||||
|
reducer.join(red_result,
|
||||||
|
reduction_value_type{view(index), view(index), index, index});
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_EQ(red_result.min_val, gold_values.first);
|
||||||
|
ASSERT_EQ(red_result.max_val, gold_values.second);
|
||||||
|
ASSERT_EQ(red_result.min_loc, gold_locs.first);
|
||||||
|
ASSERT_EQ(red_result.max_loc, gold_locs.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(std_algorithms_reducers, min_max_first_last_loc) {
|
||||||
|
using hostspace = Kokkos::HostSpace;
|
||||||
|
|
||||||
|
using view_t = Kokkos::View<double*, hostspace>;
|
||||||
|
constexpr std::size_t extent = 10;
|
||||||
|
view_t view_h("v", extent);
|
||||||
|
view_h(0) = 0.;
|
||||||
|
view_h(1) = 0.;
|
||||||
|
view_h(2) = 0.;
|
||||||
|
view_h(3) = 2.;
|
||||||
|
view_h(4) = 2.;
|
||||||
|
view_h(5) = -1.;
|
||||||
|
view_h(6) = 1.;
|
||||||
|
view_h(7) = -1.;
|
||||||
|
view_h(8) = 2.;
|
||||||
|
view_h(9) = 0.;
|
||||||
|
|
||||||
|
using index_type = int;
|
||||||
|
using view_value_type = typename view_t::value_type;
|
||||||
|
Kokkos::pair<view_value_type, view_value_type> gold_values = {-1., 2.};
|
||||||
|
Kokkos::pair<index_type, index_type> gold_indices = {5, 8};
|
||||||
|
|
||||||
|
run_min_max_test<hostspace, index_type>(
|
||||||
|
view_h, StdReducersTestEnumOrder::LeftToRight, gold_values, gold_indices);
|
||||||
|
|
||||||
|
run_min_max_test<hostspace, index_type>(
|
||||||
|
view_h, StdReducersTestEnumOrder::RightToLeft, gold_values, gold_indices);
|
||||||
|
|
||||||
|
run_min_max_test<hostspace, index_type>(
|
||||||
|
view_h, StdReducersTestEnumOrder::Random, gold_values, gold_indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Test
|
||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
template <class Scalar>
|
template <class Scalar>
|
||||||
double test_atomic(int L, int N, int M, int K, int R,
|
double test_atomic(int L, int N, int M, int K, int R,
|
||||||
Kokkos::View<const int*> offsets) {
|
Kokkos::View<const int**> offsets) {
|
||||||
Kokkos::View<Scalar*> output("Output", N);
|
Kokkos::View<Scalar*> output("Output", N);
|
||||||
Kokkos::Timer timer;
|
Kokkos::Timer timer;
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ double test_atomic(int L, int N, int M, int K, int R,
|
|||||||
|
|
||||||
template <class Scalar>
|
template <class Scalar>
|
||||||
double test_no_atomic(int L, int N, int M, int K, int R,
|
double test_no_atomic(int L, int N, int M, int K, int R,
|
||||||
Kokkos::View<const int*> offsets) {
|
Kokkos::View<const int**> offsets) {
|
||||||
Kokkos::View<Scalar*> output("Output", N);
|
Kokkos::View<Scalar*> output("Output", N);
|
||||||
Kokkos::Timer timer;
|
Kokkos::Timer timer;
|
||||||
for (int r = 0; r < R; r++)
|
for (int r = 0; r < R; r++)
|
||||||
@ -77,7 +77,7 @@ int main(int argc, char* argv[]) {
|
|||||||
int R = std::stoi(argv[6]);
|
int R = std::stoi(argv[6]);
|
||||||
int type = std::stoi(argv[7]);
|
int type = std::stoi(argv[7]);
|
||||||
|
|
||||||
Kokkos::View<int*> offsets("Offsets", L, M);
|
Kokkos::View<int**> offsets("Offsets", L, M);
|
||||||
Kokkos::Random_XorShift64_Pool<> pool(12371);
|
Kokkos::Random_XorShift64_Pool<> pool(12371);
|
||||||
Kokkos::fill_random(offsets, pool, D);
|
Kokkos::fill_random(offsets, pool, D);
|
||||||
double time = 0;
|
double time = 0;
|
||||||
|
|||||||
48
lib/kokkos/benchmarks/bytes_and_flops/bench_double.cpp
Normal file
48
lib/kokkos/benchmarks/bytes_and_flops/bench_double.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bench.hpp>
|
||||||
|
|
||||||
|
template void run_stride_unroll<double>(int N, int K, int R, int D, int U,
|
||||||
|
int F, int T, int S);
|
||||||
48
lib/kokkos/benchmarks/bytes_and_flops/bench_float.cpp
Normal file
48
lib/kokkos/benchmarks/bytes_and_flops/bench_float.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bench.hpp>
|
||||||
|
|
||||||
|
template void run_stride_unroll<float>(int N, int K, int R, int D, int U, int F,
|
||||||
|
int T, int S);
|
||||||
48
lib/kokkos/benchmarks/bytes_and_flops/bench_int32_t.cpp
Normal file
48
lib/kokkos/benchmarks/bytes_and_flops/bench_int32_t.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bench.hpp>
|
||||||
|
|
||||||
|
template void run_stride_unroll<int32_t>(int N, int K, int R, int D, int U,
|
||||||
|
int F, int T, int S);
|
||||||
48
lib/kokkos/benchmarks/bytes_and_flops/bench_int64_t.cpp
Normal file
48
lib/kokkos/benchmarks/bytes_and_flops/bench_int64_t.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
//@HEADER
|
||||||
|
// ************************************************************************
|
||||||
|
//
|
||||||
|
// Kokkos v. 3.0
|
||||||
|
// Copyright (2020) National Technology & Engineering
|
||||||
|
// Solutions of Sandia, LLC (NTESS).
|
||||||
|
//
|
||||||
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||||
|
// the U.S. Government retains certain rights in this software.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the Corporation nor the names of the
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
|
||||||
|
//
|
||||||
|
// ************************************************************************
|
||||||
|
//@HEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bench.hpp>
|
||||||
|
|
||||||
|
template void run_stride_unroll<int64_t>(int N, int K, int R, int D, int U,
|
||||||
|
int F, int T, int S);
|
||||||
@ -47,12 +47,21 @@
|
|||||||
#include <bench.hpp>
|
#include <bench.hpp>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
extern template void run_stride_unroll<float>(int, int, int, int, int, int, int,
|
||||||
|
int);
|
||||||
|
extern template void run_stride_unroll<double>(int, int, int, int, int, int,
|
||||||
|
int, int);
|
||||||
|
extern template void run_stride_unroll<int32_t>(int, int, int, int, int, int,
|
||||||
|
int, int);
|
||||||
|
extern template void run_stride_unroll<int64_t>(int, int, int, int, int, int,
|
||||||
|
int, int);
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
Kokkos::initialize();
|
Kokkos::initialize();
|
||||||
|
|
||||||
if (argc < 10) {
|
if (argc < 10) {
|
||||||
printf("Arguments: N K R D U F T S\n");
|
printf("Arguments: N K R D U F T S\n");
|
||||||
printf(" P: Precision (1==float, 2==double)\n");
|
printf(" P: Precision (1==float, 2==double, 3==int32_t, 4==int64_t)\n");
|
||||||
printf(" N,K: dimensions of the 2D array to allocate\n");
|
printf(" N,K: dimensions of the 2D array to allocate\n");
|
||||||
printf(" R: how often to loop through the K dimension with each team\n");
|
printf(" R: how often to loop through the K dimension with each team\n");
|
||||||
printf(" D: distance between loaded elements (stride)\n");
|
printf(" D: distance between loaded elements (stride)\n");
|
||||||
@ -91,8 +100,8 @@ int main(int argc, char* argv[]) {
|
|||||||
printf("D must be one of 1,2,4,8,16,32\n");
|
printf("D must be one of 1,2,4,8,16,32\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((P != 1) && (P != 2)) {
|
if ((P < 1) && (P > 2)) {
|
||||||
printf("P must be one of 1,2\n");
|
printf("P must be one of 1,2,3,4\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +111,12 @@ int main(int argc, char* argv[]) {
|
|||||||
if (P == 2) {
|
if (P == 2) {
|
||||||
run_stride_unroll<double>(N, K, R, D, U, F, T, S);
|
run_stride_unroll<double>(N, K, R, D, U, F, T, S);
|
||||||
}
|
}
|
||||||
|
if (P == 3) {
|
||||||
|
run_stride_unroll<int32_t>(N, K, R, D, U, F, T, S);
|
||||||
|
}
|
||||||
|
if (P == 4) {
|
||||||
|
run_stride_unroll<int64_t>(N, K, R, D, U, F, T, S);
|
||||||
|
}
|
||||||
|
|
||||||
Kokkos::finalize();
|
Kokkos::finalize();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -636,13 +636,13 @@ elif [[ ${HPCBIND_HAS_COMMAND} -eq 1 ]]; then
|
|||||||
if [[ ${HPCBIND_ENABLE_HWLOC_BIND} -eq 1 ]]; then
|
if [[ ${HPCBIND_ENABLE_HWLOC_BIND} -eq 1 ]]; then
|
||||||
hwloc-bind "${HPCBIND_HWLOC_CPUSET}" -- "$@" > ${HPCBIND_OUT} 2> ${HPCBIND_ERR}
|
hwloc-bind "${HPCBIND_HWLOC_CPUSET}" -- "$@" > ${HPCBIND_OUT} 2> ${HPCBIND_ERR}
|
||||||
else
|
else
|
||||||
eval "$@" > ${HPCBIND_OUT} 2> ${HPCBIND_ERR}
|
"$@" > ${HPCBIND_OUT} 2> ${HPCBIND_ERR}
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [[ ${HPCBIND_ENABLE_HWLOC_BIND} -eq 1 ]]; then
|
if [[ ${HPCBIND_ENABLE_HWLOC_BIND} -eq 1 ]]; then
|
||||||
hwloc-bind "${HPCBIND_HWLOC_CPUSET}" -- "$@" > >(tee ${HPCBIND_OUT}) 2> >(tee ${HPCBIND_ERR} >&2)
|
hwloc-bind "${HPCBIND_HWLOC_CPUSET}" -- "$@" > >(tee ${HPCBIND_OUT}) 2> >(tee ${HPCBIND_ERR} >&2)
|
||||||
else
|
else
|
||||||
eval "$@" > >(tee ${HPCBIND_OUT}) 2> >(tee ${HPCBIND_ERR} >&2)
|
"$@" > >(tee ${HPCBIND_OUT}) 2> >(tee ${HPCBIND_ERR} >&2)
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -83,9 +83,9 @@ shift
|
|||||||
# results in this command being executed:
|
# results in this command being executed:
|
||||||
# ${KOKKOS_COMPILER} -c file.cpp -o file.o
|
# ${KOKKOS_COMPILER} -c file.cpp -o file.o
|
||||||
if [[ "${KOKKOS_DEPENDENCE}" -eq "0" || "${CXX_COMPILER}" != "${1}" ]]; then
|
if [[ "${KOKKOS_DEPENDENCE}" -eq "0" || "${CXX_COMPILER}" != "${1}" ]]; then
|
||||||
debug-message $@
|
debug-message "$@"
|
||||||
# the command does not depend on Kokkos so just execute the command w/o re-directing to ${KOKKOS_COMPILER}
|
# the command does not depend on Kokkos so just execute the command w/o re-directing to ${KOKKOS_COMPILER}
|
||||||
eval $@
|
exec "$@"
|
||||||
else
|
else
|
||||||
# the executable is the C++ compiler, so we need to re-direct to ${KOKKOS_COMPILER}
|
# the executable is the C++ compiler, so we need to re-direct to ${KOKKOS_COMPILER}
|
||||||
if [ ! -f "${KOKKOS_COMPILER}" ]; then
|
if [ ! -f "${KOKKOS_COMPILER}" ]; then
|
||||||
@ -115,7 +115,7 @@ else
|
|||||||
# discard the compiler from the command
|
# discard the compiler from the command
|
||||||
shift
|
shift
|
||||||
|
|
||||||
debug-message ${KOKKOS_COMPILER} $@
|
debug-message ${KOKKOS_COMPILER} "$@"
|
||||||
# execute ${KOKKOS_COMPILER} (again, usually nvcc_wrapper)
|
# execute ${KOKKOS_COMPILER} (again, usually nvcc_wrapper)
|
||||||
${KOKKOS_COMPILER} $@
|
${KOKKOS_COMPILER} "$@"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -149,9 +149,14 @@ do
|
|||||||
*.cpp|*.cxx|*.cc|*.C|*.c++|*.cu)
|
*.cpp|*.cxx|*.cc|*.C|*.c++|*.cu)
|
||||||
cpp_files="$cpp_files $1"
|
cpp_files="$cpp_files $1"
|
||||||
;;
|
;;
|
||||||
# Ensure we only have one optimization flag because NVCC doesn't allow muliple
|
# Ensure we only have one optimization flag because NVCC doesn't allow multiple
|
||||||
-O*)
|
-O*)
|
||||||
if [ -n "$optimization_flag" ]; then
|
if [ -n "$optimization_flag" ]; then
|
||||||
|
if [ "$1" = "$optimization_flag" ]; then
|
||||||
|
# Silently consume duplicates of the same argument
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
fi
|
||||||
echo "nvcc_wrapper - *warning* you have set multiple optimization flags (-O*), only the last is used because nvcc can only accept a single optimization setting."
|
echo "nvcc_wrapper - *warning* you have set multiple optimization flags (-O*), only the last is used because nvcc can only accept a single optimization setting."
|
||||||
shared_args=${shared_args/ $optimization_flag/}
|
shared_args=${shared_args/ $optimization_flag/}
|
||||||
fi
|
fi
|
||||||
@ -222,7 +227,7 @@ do
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
#Handle known nvcc args
|
#Handle known nvcc args
|
||||||
--dryrun|--verbose|--keep|--keep-dir*|-G|-lineinfo|-expt-extended-lambda|-expt-relaxed-constexpr|--resource-usage|-Xptxas*|--fmad=*|--use_fast_math|--Wext-lambda-captures-this|-Wext-lambda-captures-this)
|
--dryrun|--verbose|--keep|--keep-dir*|-G|-lineinfo|-expt-extended-lambda|-expt-relaxed-constexpr|--resource-usage|--fmad=*|--use_fast_math|--Wext-lambda-captures-this|-Wext-lambda-captures-this)
|
||||||
cuda_args="$cuda_args $1"
|
cuda_args="$cuda_args $1"
|
||||||
;;
|
;;
|
||||||
#Handle more known nvcc args
|
#Handle more known nvcc args
|
||||||
@ -230,10 +235,10 @@ do
|
|||||||
cuda_args="$cuda_args $1"
|
cuda_args="$cuda_args $1"
|
||||||
;;
|
;;
|
||||||
#Handle known nvcc args that have an argument
|
#Handle known nvcc args that have an argument
|
||||||
-maxrregcount=*|--maxrregcount=*|-time=*)
|
-maxrregcount=*|--maxrregcount=*|-time=*|-Xptxas=*)
|
||||||
cuda_args="$cuda_args $1"
|
cuda_args="$cuda_args $1"
|
||||||
;;
|
;;
|
||||||
-maxrregcount|--default-stream|-Xnvlink|--fmad|-cudart|--cudart|-include|-time)
|
-maxrregcount|--default-stream|-Xnvlink|--fmad|-cudart|--cudart|-include|-time|-Xptxas)
|
||||||
cuda_args="$cuda_args $1 $2"
|
cuda_args="$cuda_args $1 $2"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
|||||||
@ -60,3 +60,5 @@ ELSEIF(@Kokkos_ENABLE_CUDA@ AND NOT "separable_compilation" IN_LIST Kokkos_FIND_
|
|||||||
# be mindful of the environment, pollution is bad
|
# be mindful of the environment, pollution is bad
|
||||||
UNSET(IS_NVCC)
|
UNSET(IS_NVCC)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
set(Kokkos_COMPILE_LANGUAGE @KOKKOS_COMPILE_LANGUAGE@)
|
||||||
|
|||||||
@ -13,6 +13,10 @@ ENDFOREACH()
|
|||||||
IF(NOT Kokkos_FIND_QUIETLY)
|
IF(NOT Kokkos_FIND_QUIETLY)
|
||||||
MESSAGE(STATUS "Enabled Kokkos devices: ${Kokkos_DEVICES}")
|
MESSAGE(STATUS "Enabled Kokkos devices: ${Kokkos_DEVICES}")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
IF(Kokkos_ENABLE_THREADS AND NOT DEPRECATED_CODE_3 IN_LIST Kokkos_OPTIONS) # for backward compatibility
|
||||||
|
SET(Kokkos_ENABLE_PTHREAD ON)
|
||||||
|
LIST(APPEND Kokkos_DEVICES PTHREAD)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
IF (Kokkos_ENABLE_CUDA)
|
IF (Kokkos_ENABLE_CUDA)
|
||||||
# If we are building CUDA, we have tricked CMake because we declare a CXX project
|
# If we are building CUDA, we have tricked CMake because we declare a CXX project
|
||||||
|
|||||||
@ -43,6 +43,7 @@
|
|||||||
#cmakedefine KOKKOS_ENABLE_CUDA_LDG_INTRINSIC
|
#cmakedefine KOKKOS_ENABLE_CUDA_LDG_INTRINSIC
|
||||||
#cmakedefine KOKKOS_ENABLE_IMPL_CUDA_MALLOC_ASYNC
|
#cmakedefine KOKKOS_ENABLE_IMPL_CUDA_MALLOC_ASYNC
|
||||||
#cmakedefine KOKKOS_ENABLE_HIP_RELOCATABLE_DEVICE_CODE
|
#cmakedefine KOKKOS_ENABLE_HIP_RELOCATABLE_DEVICE_CODE
|
||||||
|
#cmakedefine KOKKOS_ENABLE_HIP_MULTIPLE_KERNEL_INSTANTIATIONS
|
||||||
#cmakedefine KOKKOS_ENABLE_HPX_ASYNC_DISPATCH
|
#cmakedefine KOKKOS_ENABLE_HPX_ASYNC_DISPATCH
|
||||||
#cmakedefine KOKKOS_ENABLE_DEBUG
|
#cmakedefine KOKKOS_ENABLE_DEBUG
|
||||||
#cmakedefine KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
|
#cmakedefine KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
|
||||||
@ -112,5 +113,8 @@
|
|||||||
#cmakedefine KOKKOS_ARCH_AMD_ZEN
|
#cmakedefine KOKKOS_ARCH_AMD_ZEN
|
||||||
#cmakedefine KOKKOS_ARCH_AMD_ZEN2
|
#cmakedefine KOKKOS_ARCH_AMD_ZEN2
|
||||||
#cmakedefine KOKKOS_ARCH_AMD_ZEN3
|
#cmakedefine KOKKOS_ARCH_AMD_ZEN3
|
||||||
|
#cmakedefine KOKKOS_ARCH_VEGA
|
||||||
#cmakedefine KOKKOS_IMPL_DISABLE_SYCL_DEVICE_PRINTF
|
#cmakedefine KOKKOS_ARCH_VEGA900
|
||||||
|
#cmakedefine KOKKOS_ARCH_VEGA906
|
||||||
|
#cmakedefine KOKKOS_ARCH_VEGA908
|
||||||
|
#cmakedefine KOKKOS_ARCH_VEGA90A
|
||||||
|
|||||||
@ -29,7 +29,7 @@ ELSE()
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
IF(KOKKOS_CXX_HOST_COMPILER_ID STREQUAL PGI)
|
IF(KOKKOS_CXX_HOST_COMPILER_ID STREQUAL NVHPC)
|
||||||
SET(KOKKOS_CUDA_ERROR "Using NVHPC as host compiler requires at least CMake 3.20.1")
|
SET(KOKKOS_CUDA_ERROR "Using NVHPC as host compiler requires at least CMake 3.20.1")
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(KOKKOS_CUDA_ERROR DEFAULT_MSG)
|
SET(KOKKOS_CUDA_ERROR DEFAULT_MSG)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user