Update Kokkos library in LAMMPS to v3.6.0

This commit is contained in:
Stan Gerald Moore
2022-05-05 11:44:47 -06:00
parent bd4bbbddbe
commit b79c0bc7b4
380 changed files with 41928 additions and 8786 deletions

View File

@ -119,8 +119,8 @@ Device backends can be enabled by specifying `-DKokkos_ENABLE_X`.
* Kokkos_ENABLE_OPENMP
* Whether to build OpenMP backend
* BOOL Default: OFF
* Kokkos_ENABLE_PTHREAD
* Whether to build Pthread backend
* Kokkos_ENABLE_THREADS
* Whether to build C++ thread backend
* BOOL Default: OFF
* Kokkos_ENABLE_SERIAL
* 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
* BOOL Default: OFF
* Kokkos_ENABLE_TESTS
* Whether to build serial backend
* Whether to enable test suite
* BOOL Default: OFF
## Other Options

View File

@ -1,5 +1,120 @@
# 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)
[Full Changelog](https://github.com/kokkos/kokkos/compare/3.4.01...3.5.00)

View File

@ -1,7 +1,7 @@
# Disable in-source builds to prevent source tree corruption.
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()
# 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)
set(CMAKE_DISABLE_SOURCE_CHANGES 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 (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,
#nuke the Spack compiler
SET(SPACK_CXX $ENV{SPACK_CXX})
@ -86,7 +110,7 @@ IF(NOT KOKKOS_HAS_TRILINOS)
ENDIF()
# Always call the project command to define Kokkos_ variables
# 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 CMAKE_BUILD_TYPE)
SET(DEFAULT_BUILD_TYPE "RelWithDebInfo")
@ -111,7 +135,7 @@ ENDIF()
set(Kokkos_VERSION_MAJOR 3)
set(Kokkos_VERSION_MINOR 5)
set(Kokkos_VERSION_MINOR 6)
set(Kokkos_VERSION_PATCH 00)
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}")
@ -151,6 +175,10 @@ IF(NOT MSVC)
GLOBAL_APPEND(KOKKOS_LINK_OPTIONS -DKOKKOS_DEPENDENCE)
ENDIF()
IF(Kokkos_ENABLE_TESTS AND NOT KOKKOS_HAS_TRILINOS)
find_package(GTest)
ENDIF()
# Include a set of Kokkos-specific wrapper functions that
# will either call raw CMake or TriBITS
# These are functions like KOKKOS_INCLUDE_DIRECTORIES
@ -174,10 +202,6 @@ KOKKOS_SETUP_BUILD_ENVIRONMENT()
# 7) Export and install targets
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_INT_LIBRARIES kokkos kokkoscore kokkoscontainers kokkosalgorithms)

View File

@ -11,13 +11,13 @@ CXXFLAGS += $(SHFLAGS)
endif
KOKKOS_VERSION_MAJOR = 3
KOKKOS_VERSION_MINOR = 5
KOKKOS_VERSION_MINOR = 6
KOKKOS_VERSION_PATCH = 00
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 ?= "Pthread"
#KOKKOS_DEVICES ?= "Threads"
# Options:
# Intel: KNC,KNL,SNB,HSW,BDW,SKX
# 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 ?= ""
# Options: c++14,c++1y,c++17,c++1z,c++2a
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
KOKKOS_OPTIONS ?= "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 ?= ""
KOKKOS_CMAKE ?= "no"
KOKKOS_TRIBITS ?= "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_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)
# deprecated
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_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.
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_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_PTHREADS), 0)
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 0)
ifeq ($(KOKKOS_INTERNAL_USE_HPX), 0)
KOKKOS_INTERNAL_USE_SERIAL := 1
endif
@ -126,7 +134,7 @@ endif
ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
KOKKOS_DEVICELIST += OpenMP
endif
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
KOKKOS_DEVICELIST += Threads
endif
ifeq ($(KOKKOS_INTERNAL_USE_HPX), 1)
@ -472,7 +480,7 @@ ifneq ($(KOKKOS_CMAKE), yes)
# CXXLDFLAGS is used together with CXXFLAGS in a combined compile/link command
KOKKOS_CXXLDFLAGS = -L$(shell pwd)
endif
KOKKOS_LINK_FLAGS =
KOKKOS_LINK_FLAGS =
KOKKOS_SRC =
KOKKOS_HEADERS =
@ -504,7 +512,7 @@ tmp := $(call kokkos_append_header,'$H''endif')
tmp := $(call kokkos_append_header,"")
tmp := $(call kokkos_append_header,"$H""define KOKKOS_VERSION $(KOKKOS_VERSION)")
tmp := $(call kokkos_append_header,"")
tmp := $(call kokkos_append_header,"/* Execution Spaces */")
ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
@ -531,7 +539,7 @@ ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
tmp := $(call kokkos_append_header,'$H''define KOKKOS_ENABLE_OPENMP')
endif
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
tmp := $(call kokkos_append_header,"$H""define KOKKOS_ENABLE_THREADS")
endif
@ -952,18 +960,8 @@ ifeq ($(KOKKOS_INTERNAL_USE_ARCH_POWER8), 1)
ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1)
else
ifeq ($(KOKKOS_INTERNAL_COMPILER_XL), 1)
KOKKOS_CXXFLAGS += -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
KOKKOS_CXXFLAGS += -mcpu=power8 -mtune=power8
KOKKOS_LDFLAGS += -mcpu=power8 -mtune=power8
endif
endif
@ -973,18 +971,8 @@ ifeq ($(KOKKOS_INTERNAL_USE_ARCH_POWER9), 1)
ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1)
else
ifeq ($(KOKKOS_INTERNAL_COMPILER_XL), 1)
KOKKOS_CXXFLAGS += -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
KOKKOS_CXXFLAGS += -mcpu=power9 -mtune=power9
KOKKOS_LDFLAGS += -mcpu=power9 -mtune=power9
endif
endif
@ -1202,32 +1190,32 @@ endif
ifeq ($(KOKKOS_INTERNAL_USE_HIP), 1)
# Lets start with adding architecture defines
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_VEGA")
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx900
endif
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_VEGA")
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx906
endif
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_VEGA")
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx908
endif
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_VEGA")
KOKKOS_INTERNAL_HIP_ARCH_FLAG := --amdgpu-target=gfx90a
endif
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
endif
KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/HIP/*.hpp)
KOKKOS_CXXFLAGS+=$(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)
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")
else
ifeq ($(KOKKOS_INTERNAL_ENABLE_DESUL_ATOMICS), 1)
$(error Contradictory Desul atomics options: KOKKOS_OPTIONS=$(KOKKOS_OPTIONS) )
endif
endif
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)
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 <setup/Kokkos_Setup_SYCL.hpp>","KokkosCore_Config_SetupBackend.hpp")
endif
ifeq ($(KOKKOS_INTERNAL_USE_HIP), 1)
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 <decl/Kokkos_Declare_OPENMP.hpp>","KokkosCore_Config_DeclareBackend.hpp")
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 <decl/Kokkos_Declare_THREADS.hpp>","KokkosCore_Config_DeclareBackend.hpp")
endif
@ -1367,7 +1358,7 @@ KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/containers/src/impl/*.cpp)
ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
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
endif
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)
endif
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/Threads/*.cpp)
KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/Threads/*.hpp)
KOKKOS_LIBS += -lpthread
@ -1453,14 +1444,6 @@ ifeq ($(KOKKOS_INTERNAL_USE_HPX), 1)
KOKKOS_TPL_LIBRARY_NAMES += hpx
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.
ifneq ($(KOKKOS_INTERNAL_USE_MEMKIND), 1)
KOKKOS_SRC := $(filter-out $(KOKKOS_PATH)/core/src/impl/Kokkos_HBWSpace.cpp,$(KOKKOS_SRC))
@ -1507,7 +1490,7 @@ libkokkos.a: $(KOKKOS_OBJ_LINK) $(KOKKOS_SRC) $(KOKKOS_HEADERS)
ar cr libkokkos.a $(KOKKOS_OBJ_LINK)
ranlib libkokkos.a
print-cxx-flags:
print-cxx-flags:
echo "$(KOKKOS_CXXFLAGS)"
KOKKOS_LINK_DEPENDS=libkokkos.a

View File

@ -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
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
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
$(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
@ -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
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
$(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

View File

@ -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.
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
we are unaware off.
we are unaware of.
* GCC: 5.3.0
* Clang: 4.0.0
* Intel: 17.0.1
* NVCC: 9.2.88
* NVC++: 21.5
* ROCM: 4.3
* ROCm: 4.3
* MSVC: 19.29
* IBM XL: 16.1.1
* Fujitsu: 4.5.0
@ -70,7 +70,7 @@ we are unaware off.
* MSVC: 19.29
* ARM/Clang: 20.1
* IBM XL: 16.1.1
* ROCM: 4.3.0
* ROCm: 4.3.0
### Build system:
@ -80,7 +80,7 @@ we are unaware off.
Primary tested compiler are passing in release mode
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:
* 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
features an application needs. For example there is only one default
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
installation time. Building Kokkos inline uses largely the same process
as compiling an application against an installed Kokkos library.

View File

@ -24,20 +24,22 @@ By default, Spack doesn't 'see' anything on your system - including things like
This can be limited by adding a `packages.yaml` to your `$HOME/.spack` folder that includes CMake (and CUDA, if applicable). For example, your `packages.yaml` file could be:
````yaml
packages:
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
cmake:
modules:
cmake: [cmake/3.16.8]
paths:
cmake:
/opt/local/ppc64le/cmake/3.16.8
buildable: false
cuda:
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:
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 `buildable` flag is useful to make sure Spack crashes if there is a path error,

View File

@ -10,6 +10,7 @@ KOKKOS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
FILE(GLOB ALGO_HEADERS *.hpp)
FILE(GLOB ALGO_SOURCES *.cpp)
LIST(APPEND ALGO_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}_config.h)
APPEND_GLOB(ALGO_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/std_algorithms/*.hpp)
INSTALL (
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"

View File

@ -466,6 +466,25 @@ struct rand<Generator, Kokkos::Experimental::half_t> {
};
#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>
struct rand<Generator, float> {
KOKKOS_INLINE_FUNCTION
@ -499,7 +518,7 @@ struct rand<Generator, double> {
};
template <class Generator>
struct rand<Generator, Kokkos::complex<float> > {
struct rand<Generator, Kokkos::complex<float>> {
KOKKOS_INLINE_FUNCTION
static Kokkos::complex<float> max() {
return Kokkos::complex<float>(1.0, 1.0);
@ -528,7 +547,7 @@ struct rand<Generator, Kokkos::complex<float> > {
};
template <class Generator>
struct rand<Generator, Kokkos::complex<double> > {
struct rand<Generator, Kokkos::complex<double>> {
KOKKOS_INLINE_FUNCTION
static Kokkos::complex<double> max() {
return Kokkos::complex<double>(1.0, 1.0);
@ -617,24 +636,23 @@ struct Random_XorShift1024_UseCArrayState<Kokkos::Experimental::OpenMPTarget>
: std::false_type {};
#endif
template <class ExecutionSpace>
template <class DeviceType>
struct Random_UniqueIndex {
using locks_view_type = View<int**, ExecutionSpace>;
using locks_view_type = View<int**, DeviceType>;
KOKKOS_FUNCTION
static int get_state_idx(const locks_view_type) {
#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
const int i = ExecutionSpace::impl_hardware_thread_id();
return i;
#else
return 0;
#endif
KOKKOS_IF_ON_HOST(
(return DeviceType::execution_space::impl_hardware_thread_id();))
KOKKOS_IF_ON_DEVICE((return 0;))
}
};
#ifdef KOKKOS_ENABLE_CUDA
template <>
struct Random_UniqueIndex<Kokkos::Cuda> {
using locks_view_type = View<int**, Kokkos::Cuda>;
template <class MemorySpace>
struct Random_UniqueIndex<Kokkos::Device<Kokkos::Cuda, MemorySpace>> {
using locks_view_type =
View<int**, Kokkos::Device<Kokkos::Cuda, MemorySpace>>;
KOKKOS_FUNCTION
static int get_state_idx(const locks_view_type& locks_) {
#ifdef __CUDA_ARCH__
@ -660,9 +678,11 @@ struct Random_UniqueIndex<Kokkos::Cuda> {
#endif
#ifdef KOKKOS_ENABLE_HIP
template <>
struct Random_UniqueIndex<Kokkos::Experimental::HIP> {
using locks_view_type = View<int**, Kokkos::Experimental::HIP>;
template <class MemorySpace>
struct Random_UniqueIndex<
Kokkos::Device<Kokkos::Experimental::HIP, MemorySpace>> {
using locks_view_type =
View<int**, Kokkos::Device<Kokkos::Experimental::HIP, MemorySpace>>;
KOKKOS_FUNCTION
static int get_state_idx(const locks_view_type& locks_) {
#ifdef __HIP_DEVICE_COMPILE__
@ -688,18 +708,37 @@ struct Random_UniqueIndex<Kokkos::Experimental::HIP> {
#endif
#ifdef KOKKOS_ENABLE_SYCL
template <>
struct Random_UniqueIndex<Kokkos::Experimental::SYCL> {
using locks_view_type = View<int**, Kokkos::Experimental::SYCL>;
template <class MemorySpace>
struct Random_UniqueIndex<
Kokkos::Device<Kokkos::Experimental::SYCL, MemorySpace>> {
using locks_view_type =
View<int**, Kokkos::Device<Kokkos::Experimental::SYCL, MemorySpace>>;
KOKKOS_FUNCTION
static int get_state_idx(const locks_view_type& locks_) {
#ifdef KOKKOS_ARCH_INTEL_GPU
int i = Kokkos::Impl::clock_tic() % locks_.extent(0);
#else
int i = 0;
#endif
auto item = sycl::ext::oneapi::experimental::this_nd_item<3>();
std::size_t threadIdx[3] = {item.get_local_id(2), item.get_local_id(1),
item.get_local_id(0)};
std::size_t blockIdx[3] = {item.get_group(2), item.get_group(1),
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)) {
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;
}
@ -707,9 +746,12 @@ struct Random_UniqueIndex<Kokkos::Experimental::SYCL> {
#endif
#ifdef KOKKOS_ENABLE_OPENMPTARGET
template <>
struct Random_UniqueIndex<Kokkos::Experimental::OpenMPTarget> {
using locks_view_type = View<int**, Kokkos::Experimental::OpenMPTarget>;
template <class MemorySpace>
struct Random_UniqueIndex<
Kokkos::Device<Kokkos::Experimental::OpenMPTarget, MemorySpace>> {
using locks_view_type =
View<int**,
Kokkos::Device<Kokkos::Experimental::OpenMPTarget, MemorySpace>>;
KOKKOS_FUNCTION
static int get_state_idx(const locks_view_type& locks) {
const int team_size = omp_get_num_threads();
@ -873,10 +915,13 @@ class Random_XorShift64 {
template <class DeviceType = Kokkos::DefaultExecutionSpace>
class Random_XorShift64_Pool {
public:
using device_type = typename DeviceType::device_type;
private:
using execution_space = typename DeviceType::execution_space;
using locks_type = View<int**, execution_space>;
using state_data_type = View<uint64_t**, DeviceType>;
using execution_space = typename device_type::execution_space;
using locks_type = View<int**, device_type>;
using state_data_type = View<uint64_t**, device_type>;
locks_type locks_;
state_data_type state_;
int num_states_;
@ -884,7 +929,6 @@ class Random_XorShift64_Pool {
public:
using generator_type = Random_XorShift64<DeviceType>;
using device_type = DeviceType;
KOKKOS_INLINE_FUNCTION
Random_XorShift64_Pool() {
@ -923,8 +967,10 @@ class Random_XorShift64_Pool {
state_ = state_data_type("Kokkos::Random_XorShift64::state", num_states_,
padding_);
typename state_data_type::HostMirror h_state = create_mirror_view(state_);
typename locks_type::HostMirror h_lock = create_mirror_view(locks_);
typename state_data_type::HostMirror h_state =
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.
Random_XorShift64<typename state_data_type::HostMirror::execution_space>
@ -947,8 +993,7 @@ class Random_XorShift64_Pool {
KOKKOS_INLINE_FUNCTION
Random_XorShift64<DeviceType> get_state() const {
const int i =
Impl::Random_UniqueIndex<execution_space>::get_state_idx(locks_);
const int i = Impl::Random_UniqueIndex<device_type>::get_state_idx(locks_);
return Random_XorShift64<DeviceType>(state_(i, 0), i);
}
@ -1119,11 +1164,14 @@ class Random_XorShift1024 {
template <class DeviceType = Kokkos::DefaultExecutionSpace>
class Random_XorShift1024_Pool {
public:
using device_type = typename DeviceType::device_type;
private:
using execution_space = typename DeviceType::execution_space;
using locks_type = View<int**, execution_space>;
using int_view_type = View<int**, DeviceType>;
using state_data_type = View<uint64_t * [16], DeviceType>;
using execution_space = typename device_type::execution_space;
using locks_type = View<int**, device_type>;
using int_view_type = View<int**, device_type>;
using state_data_type = View<uint64_t * [16], device_type>;
locks_type locks_;
state_data_type state_;
@ -1135,8 +1183,6 @@ class Random_XorShift1024_Pool {
public:
using generator_type = Random_XorShift1024<DeviceType>;
using device_type = DeviceType;
KOKKOS_INLINE_FUNCTION
Random_XorShift1024_Pool() { num_states_ = 0; }
@ -1175,9 +1221,12 @@ class Random_XorShift1024_Pool {
state_ = state_data_type("Kokkos::Random_XorShift1024::state", num_states_);
p_ = int_view_type("Kokkos::Random_XorShift1024::p", num_states_, padding_);
typename state_data_type::HostMirror h_state = create_mirror_view(state_);
typename locks_type::HostMirror h_lock = create_mirror_view(locks_);
typename int_view_type::HostMirror h_p = create_mirror_view(p_);
typename state_data_type::HostMirror h_state =
Kokkos::create_mirror_view(Kokkos::WithoutInitializing, state_);
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.
Random_XorShift64<typename state_data_type::HostMirror::execution_space>
@ -1203,8 +1252,7 @@ class Random_XorShift1024_Pool {
KOKKOS_INLINE_FUNCTION
Random_XorShift1024<DeviceType> get_state() const {
const int i =
Impl::Random_UniqueIndex<execution_space>::get_state_idx(locks_);
const int i = Impl::Random_UniqueIndex<device_type>::get_state_idx(locks_);
return Random_XorShift1024<DeviceType>(state_, p_(i, 0), i);
};
@ -1224,265 +1272,34 @@ class Random_XorShift1024_Pool {
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,
class IndexType>
struct fill_random_functor_begin_end;
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;
ViewType a;
RandomPool rand_pool;
typename ViewType::const_value_type range;
typename ViewType::const_value_type begin, end;
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_) {}
fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
typename ViewType::const_value_type begin_,
typename ViewType::const_value_type end_)
: a(a_), rand_pool(rand_pool_), begin(begin_), end(end_) {}
KOKKOS_INLINE_FUNCTION
void operator()(const IndexType& i) const {
void operator()(IndexType) 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)))
a(idx) = Rand::draw(gen, range);
}
a() = Rand::draw(gen, begin, end);
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>
struct fill_random_functor_begin_end<ViewType, RandomPool, loops, 1,
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>
void fill_random(ViewType a, RandomPool g,
typename ViewType::const_value_type begin,
@ -1776,6 +1580,23 @@ void fill_random(ViewType a, RandomPool g,
ViewType::Rank, IndexType>(
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
#endif

View File

@ -437,16 +437,41 @@ struct BinOp1D {
BinOp1D(int max_bins__, typename KeyViewType::const_value_type min,
typename KeyViewType::const_value_type max)
: 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),
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
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 {
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
KOKKOS_INLINE_FUNCTION
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)),
Impl::min_max_functor<ViewType>(view), reducer);
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(
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.sort(exec, view);
}

View 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

View 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

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -6,70 +6,153 @@ KOKKOS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../src )
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)
IF(Kokkos_ENABLE_OPENMP)
LIST(APPEND ALGORITHM_SOURCES
TestOpenMP_Sort1D.cpp
TestOpenMP_Sort3D.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()
string(TOUPPER ${Tag} DEVICE)
string(TOLOWER ${Tag} dir)
if(Kokkos_ENABLE_${DEVICE})
set(dir ${CMAKE_CURRENT_BINARY_DIR})
set(file ${dir}/Test${Tag}.cpp)
# Write to a temporary intermediate file and call configure_file to avoid
# updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
file(WRITE ${dir}/dummy.cpp
"#include <Test${Tag}_Category.hpp>\n"
"#include <TestRandomCommon.hpp>\n"
"#include <TestSortCommon.hpp>\n"
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_Sort3D.cpp
TestOpenMP_SortDynamicView.cpp
)
endif()
set(file ${dir}/TestRandomAndSort.cpp)
# Write to a temporary intermediate file and call configure_file to avoid
# updating timestamps triggering unnecessary rebuilds on subsequent cmake runs.
file(WRITE ${dir}/dummy.cpp
"#include <Test${Tag}_Category.hpp>\n"
"#include <TestRandomCommon.hpp>\n"
"#include <TestSortCommon.hpp>\n"
)
configure_file(${dir}/dummy.cpp ${file})
list(APPEND ALGORITHM_SOURCES ${file})
configure_file(${dir}/dummy.cpp ${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()
endforeach()
KOKKOS_ADD_EXECUTABLE_AND_TEST(
UnitTest
UnitTest_RandomAndSort
SOURCES
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
)

View File

@ -45,7 +45,7 @@ ifeq ($(KOKKOS_INTERNAL_USE_HIP), 1)
TEST_TARGETS += test-hip
endif
ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
ifeq ($(KOKKOS_INTERNAL_USE_THREADS), 1)
OBJ_THREADS = TestThreads.o UnitTestMain.o gtest-all.o
TARGETS += KokkosAlgorithms_UnitTest_Threads
TEST_TARGETS += test-threads

View File

@ -47,6 +47,7 @@
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <Kokkos_DynRankView.hpp>
#include <Kokkos_Timer.hpp>
#include <Kokkos_Core.hpp>
#include <Kokkos_Random.hpp>
@ -327,10 +328,6 @@ template <class RandomGenerator, class Scalar>
struct test_random_scalar {
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(
typename test_random_functor<RandomGenerator, int>::type_1d& density_1d,
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;
double covariance_eps =
result.covariance / num_draws / 2 / variance_expect;
pass_mean = ((-tolerance < mean_eps) && (tolerance > mean_eps)) ? 1 : 0;
pass_var = ((-1.5 * tolerance < variance_eps) &&
(1.5 * tolerance > variance_eps))
? 1
: 0;
pass_covar = ((-2.0 * tolerance < covariance_eps) &&
(2.0 * tolerance > covariance_eps))
? 1
: 0;
cout << "Pass: " << pass_mean << " " << pass_var << " " << mean_eps << " "
<< variance_eps << " " << covariance_eps << " || " << tolerance
<< endl;
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
if (!std::is_same<Scalar, Kokkos::Experimental::bhalf_t>::value) {
#endif
EXPECT_LT(std::abs(mean_eps), tolerance);
EXPECT_LT(std::abs(variance_eps), 1.5 * tolerance);
EXPECT_LT(std::abs(covariance_eps), 2.0 * tolerance);
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
}
#endif
}
{
cout << " -- Testing 1-D histogram" << endl;
@ -399,17 +393,15 @@ struct test_random_scalar {
}
#endif
pass_hist1d_mean =
((-mean_eps_expect < mean_eps) && (mean_eps_expect > mean_eps)) ? 1
: 0;
pass_hist1d_var = ((-variance_eps_expect < variance_eps) &&
(variance_eps_expect > variance_eps))
? 1
: 0;
pass_hist1d_covar = ((-covariance_eps_expect < covariance_eps) &&
(covariance_eps_expect > covariance_eps))
? 1
: 0;
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
if (!std::is_same<Scalar, Kokkos::Experimental::bhalf_t>::value) {
#endif
EXPECT_LT(std::abs(mean_eps), mean_eps_expect);
EXPECT_LT(std::abs(variance_eps), variance_eps_expect);
EXPECT_LT(std::abs(covariance_eps), covariance_eps_expect);
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
}
#endif
cout << "Density 1D: " << mean_eps << " " << variance_eps << " "
<< (result.covariance / HIST_DIM1D / HIST_DIM1D) << " || "
@ -445,16 +437,15 @@ struct test_random_scalar {
}
#endif
pass_hist3d_mean =
((-tolerance < mean_eps) && (tolerance > mean_eps)) ? 1 : 0;
pass_hist3d_var = ((-variance_factor * tolerance < variance_eps) &&
(variance_factor * tolerance > variance_eps))
? 1
: 0;
pass_hist3d_covar = ((-variance_factor * tolerance < covariance_eps) &&
(variance_factor * tolerance > covariance_eps))
? 1
: 0;
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
if (!std::is_same<Scalar, Kokkos::Experimental::bhalf_t>::value) {
#endif
EXPECT_LT(std::abs(mean_eps), tolerance);
EXPECT_LT(std::abs(variance_eps), variance_factor);
EXPECT_LT(std::abs(covariance_eps), variance_factor);
#if defined(KOKKOS_BHALF_T_IS_FLOAT) && !KOKKOS_BHALF_T_IS_FLOAT
}
#endif
cout << "Density 3D: " << mean_eps << " " << variance_eps << " "
<< result.covariance / HIST_DIM1D / HIST_DIM1D << " || " << tolerance
@ -479,106 +470,79 @@ void test_random(unsigned int num_draws) {
cout << "Test Scalar=int" << endl;
test_random_scalar<RandomGenerator, int> test_int(density_1d, density_3d,
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_3d, 0);
cout << "Test Scalar=unsigned int" << endl;
test_random_scalar<RandomGenerator, unsigned int> test_uint(
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_3d, 0);
cout << "Test Scalar=int64_t" << endl;
test_random_scalar<RandomGenerator, int64_t> test_int64(
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_3d, 0);
cout << "Test Scalar=uint64_t" << endl;
test_random_scalar<RandomGenerator, uint64_t> test_uint64(
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_3d, 0);
cout << "Test Scalar=half" << endl;
test_random_scalar<RandomGenerator, Kokkos::Experimental::half_t> test_half(
density_1d, density_3d, pool, num_draws);
ASSERT_EQ(test_half.pass_mean, 1);
ASSERT_EQ(test_half.pass_var, 1);
ASSERT_EQ(test_half.pass_covar, 1);
ASSERT_EQ(test_half.pass_hist1d_mean, 1);
ASSERT_EQ(test_half.pass_hist1d_var, 1);
ASSERT_EQ(test_half.pass_hist1d_covar, 1);
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_3d, 0);
cout << "Test Scalar=bhalf" << endl;
test_random_scalar<RandomGenerator, Kokkos::Experimental::bhalf_t> test_bhalf(
density_1d, density_3d, pool, num_draws);
deep_copy(density_1d, 0);
deep_copy(density_3d, 0);
cout << "Test Scalar=float" << endl;
test_random_scalar<RandomGenerator, float> test_float(density_1d, density_3d,
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_3d, 0);
cout << "Test Scalar=double" << endl;
test_random_scalar<RandomGenerator, double> test_double(
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
template <typename ExecutionSpace>
@ -593,6 +557,9 @@ void test_random_xorshift64() {
Impl::test_random<Kokkos::Random_XorShift64_Pool<
Kokkos::Device<ExecutionSpace, typename ExecutionSpace::memory_space>>>(
num_draws);
Impl::TestDynRankView<ExecutionSpace,
Kokkos::Random_XorShift64_Pool<ExecutionSpace>>(10000)
.run();
}
template <typename ExecutionSpace>
@ -608,6 +575,9 @@ void test_random_xorshift1024() {
Impl::test_random<Kokkos::Random_XorShift1024_Pool<
Kokkos::Device<ExecutionSpace, typename ExecutionSpace::memory_space>>>(
num_draws);
Impl::TestDynRankView<ExecutionSpace,
Kokkos::Random_XorShift1024_Pool<ExecutionSpace>>(10000)
.run();
}
} // namespace Test

View 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

View File

@ -164,8 +164,8 @@ void test_1D_sort_impl(unsigned int n, bool force_kokkos) {
unsigned int equal_sum =
(ratio > (1.0 - epsilon)) && (ratio < (1.0 + epsilon)) ? 1 : 0;
ASSERT_EQ(sort_fails, 0);
ASSERT_EQ(equal_sum, 1);
ASSERT_EQ(sort_fails, 0u);
ASSERT_EQ(equal_sum, 1u);
}
template <class ExecutionSpace, typename KeyType>
@ -215,8 +215,8 @@ void test_3D_sort_impl(unsigned int n) {
if (sort_fails)
printf("3D Sort Sum: %f %f Fails: %u\n", sum_before, sum_after, sort_fails);
ASSERT_EQ(sort_fails, 0);
ASSERT_EQ(equal_sum, 1);
ASSERT_EQ(sort_fails, 0u);
ASSERT_EQ(equal_sum, 1u);
}
//----------------------------------------------------------------------------
@ -279,8 +279,8 @@ void test_dynamic_view_sort_impl(unsigned int n) {
<< std::endl;
}
ASSERT_EQ(sort_fails, 0);
ASSERT_EQ(equal_sum, 1);
ASSERT_EQ(sort_fails, 0u);
ASSERT_EQ(equal_sum, 1u);
}
//----------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View 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

View File

@ -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; }

View File

@ -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

View 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

View 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

View 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

View File

@ -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

View 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

View 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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View 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

View 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

View 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

View File

@ -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

View File

@ -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

View 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

View 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

View 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 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

View 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

View 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

View File

@ -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

View File

@ -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

View 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

View 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

View 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

View 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

View File

@ -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

View 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

View 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

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View 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

View 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

View File

@ -4,7 +4,7 @@
template <class Scalar>
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::Timer timer;
@ -26,7 +26,7 @@ double test_atomic(int L, int N, int M, int K, int R,
template <class Scalar>
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::Timer timer;
for (int r = 0; r < R; r++)
@ -77,7 +77,7 @@ int main(int argc, char* argv[]) {
int R = std::stoi(argv[6]);
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::fill_random(offsets, pool, D);
double time = 0;

View 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);

View 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);

View 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);

View 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);

View File

@ -47,12 +47,21 @@
#include <bench.hpp>
#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[]) {
Kokkos::initialize();
if (argc < 10) {
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(" R: how often to loop through the K dimension with each team\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");
return 0;
}
if ((P != 1) && (P != 2)) {
printf("P must be one of 1,2\n");
if ((P < 1) && (P > 2)) {
printf("P must be one of 1,2,3,4\n");
return 0;
}
@ -102,6 +111,12 @@ int main(int argc, char* argv[]) {
if (P == 2) {
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();
}

View File

@ -135,7 +135,7 @@ function show_help {
echo " P.hpcbind.N, P.stdout.N and P.stderr.N where P is "
echo " the prefix and N is the rank (no spaces)"
echo " --output-mode=<Op> How console output should be handled."
echo " Options are all, rank0, and none. Default: rank0"
echo " Options are all, rank0, and none. Default: rank0"
echo " --lstopo Show bindings in lstopo"
echo " --save-topology=<Xml> Save the topology to the given xml file"
echo " --load-topology=<Xml> Load a previously saved topology from an xml file"
@ -636,13 +636,13 @@ elif [[ ${HPCBIND_HAS_COMMAND} -eq 1 ]]; then
if [[ ${HPCBIND_ENABLE_HWLOC_BIND} -eq 1 ]]; then
hwloc-bind "${HPCBIND_HWLOC_CPUSET}" -- "$@" > ${HPCBIND_OUT} 2> ${HPCBIND_ERR}
else
eval "$@" > ${HPCBIND_OUT} 2> ${HPCBIND_ERR}
"$@" > ${HPCBIND_OUT} 2> ${HPCBIND_ERR}
fi
else
if [[ ${HPCBIND_ENABLE_HWLOC_BIND} -eq 1 ]]; then
hwloc-bind "${HPCBIND_HWLOC_CPUSET}" -- "$@" > >(tee ${HPCBIND_OUT}) 2> >(tee ${HPCBIND_ERR} >&2)
else
eval "$@" > >(tee ${HPCBIND_OUT}) 2> >(tee ${HPCBIND_ERR} >&2)
"$@" > >(tee ${HPCBIND_OUT}) 2> >(tee ${HPCBIND_ERR} >&2)
fi
fi
fi

View File

@ -83,9 +83,9 @@ shift
# results in this command being executed:
# ${KOKKOS_COMPILER} -c file.cpp -o file.o
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}
eval $@
exec "$@"
else
# the executable is the C++ compiler, so we need to re-direct to ${KOKKOS_COMPILER}
if [ ! -f "${KOKKOS_COMPILER}" ]; then
@ -115,7 +115,7 @@ else
# discard the compiler from the command
shift
debug-message ${KOKKOS_COMPILER} $@
debug-message ${KOKKOS_COMPILER} "$@"
# execute ${KOKKOS_COMPILER} (again, usually nvcc_wrapper)
${KOKKOS_COMPILER} $@
${KOKKOS_COMPILER} "$@"
fi

View File

@ -149,11 +149,16 @@ do
*.cpp|*.cxx|*.cc|*.C|*.c++|*.cu)
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*)
if [ -n "$optimization_flag" ]; then
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/}
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."
shared_args=${shared_args/ $optimization_flag/}
fi
if [ "$1" = "-O" ]; then
optimization_flag="-O2"
@ -222,7 +227,7 @@ do
fi
;;
#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"
;;
#Handle more known nvcc args
@ -230,10 +235,10 @@ do
cuda_args="$cuda_args $1"
;;
#Handle known nvcc args that have an argument
-maxrregcount=*|--maxrregcount=*|-time=*)
-maxrregcount=*|--maxrregcount=*|-time=*|-Xptxas=*)
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"
shift
;;

View File

@ -60,3 +60,5 @@ ELSEIF(@Kokkos_ENABLE_CUDA@ AND NOT "separable_compilation" IN_LIST Kokkos_FIND_
# be mindful of the environment, pollution is bad
UNSET(IS_NVCC)
ENDIF()
set(Kokkos_COMPILE_LANGUAGE @KOKKOS_COMPILE_LANGUAGE@)

View File

@ -13,6 +13,10 @@ ENDFOREACH()
IF(NOT Kokkos_FIND_QUIETLY)
MESSAGE(STATUS "Enabled Kokkos devices: ${Kokkos_DEVICES}")
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 we are building CUDA, we have tricked CMake because we declare a CXX project

View File

@ -43,6 +43,7 @@
#cmakedefine KOKKOS_ENABLE_CUDA_LDG_INTRINSIC
#cmakedefine KOKKOS_ENABLE_IMPL_CUDA_MALLOC_ASYNC
#cmakedefine KOKKOS_ENABLE_HIP_RELOCATABLE_DEVICE_CODE
#cmakedefine KOKKOS_ENABLE_HIP_MULTIPLE_KERNEL_INSTANTIATIONS
#cmakedefine KOKKOS_ENABLE_HPX_ASYNC_DISPATCH
#cmakedefine KOKKOS_ENABLE_DEBUG
#cmakedefine KOKKOS_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK
@ -112,5 +113,8 @@
#cmakedefine KOKKOS_ARCH_AMD_ZEN
#cmakedefine KOKKOS_ARCH_AMD_ZEN2
#cmakedefine KOKKOS_ARCH_AMD_ZEN3
#cmakedefine KOKKOS_IMPL_DISABLE_SYCL_DEVICE_PRINTF
#cmakedefine KOKKOS_ARCH_VEGA
#cmakedefine KOKKOS_ARCH_VEGA900
#cmakedefine KOKKOS_ARCH_VEGA906
#cmakedefine KOKKOS_ARCH_VEGA908
#cmakedefine KOKKOS_ARCH_VEGA90A

View File

@ -29,7 +29,7 @@ ELSE()
ENDIF()
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")
ELSE()
SET(KOKKOS_CUDA_ERROR DEFAULT_MSG)

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