Skip to content

Commit

Permalink
Develop stream 2024-09-10 (#605)
Browse files Browse the repository at this point in the history
* Make use of HIP vector types in rocprim

* Format device_merge_sort_mergepath.hpp to simplify future changes

The files has indents not compatible with the current formatting style,
small changes in the code lead to incorrect auto-formatting.

* Support large indices in device_merge_sort, add tests

* Use BlockSize instead of rocprim::flat_block_size() in device_merge_sort

BlockSize is known at compile-time, while flat_block_size() computes a flat index
from 3 dimensions.

* Fix a rare bug in reduce_by_key with large indices

For some sizes d_global_head_count may be updated twice in
reduce_by_key_init_kernel: by the 0-th thread and by the save_index-th
thread. This is possible when for grid_size * block_size > number_of_tiles - 1,
i.e. number_of_tiles is sligthtly smaller than number_of_tiles_launch so the last
block has a thread with id = number_of_tiles - 1.

* Only use LDS bank conflict resolution in block_exchange when size per thread is higher than 128 bits

Changed bank_conflict_padding for smaller types

* test(test_*_iterator): fix warnings from the deprecation of std::ostream returning << operator for iterators

* ci: set up sccache

* ci(.gitlab-ci.yml): allow passing benchmark seed as variable

* allow const inputs for rocprim::partial_sort_copy

* Add new generate_limit tool to fix numeric_limits not working on custom type

* Changes to fix clang-format

* Added documentation for (non-)stable sorts

* Fixed block_radix_sort test to check stablity

* updated 3 examples of block_sort by specifying items per thread

* corrected grammar in examples

* Apply 1 suggestion(s) to 1 file(s)

Co-authored-by: Nick Breed <[email protected]>

* kept one example with the default behaviour

* key-value example, corrected key type

* fix: fixed incorrect definition and use of rocprim specific type traits for 128-bit integers

This fixes an issue where in certain situations where using radix codec on 128-bit integers would not compile due to ambiguity.

* Remove hcc path from masked_bit_count

* Fix data generation in tests: tailing items may be uninitialized

* find_first_of: Add a naive implementation

* find_first_of: Add a specialized kernel with early-exit

* find_first_of: Extend tests, add a test for large indices

* find_first_of: Use ordered_block_id for better load balancing between CUs

* find_first_of: Implement autotuning

* find_first_of: Add docs

* Add test_ordered_block_id

* Update copyright date and code format

* Add a test for 10000 blocks and a timer

* Added find_first_of to rocprim header

* Fix build error after adding headers

* fix: fix doxygen warning due to __launch_bounds__

---------

Co-authored-by: Nick Breed <[email protected]>
Co-authored-by: Anton Gorenko <[email protected]>
Co-authored-by: Nara Prasetya <[email protected]>
Co-authored-by: Beatriz Navidad Vilches <[email protected]>
Co-authored-by: milo <[email protected]>
Co-authored-by: Cenxuan Tian <[email protected]>
  • Loading branch information
7 people authored Oct 25, 2024
1 parent 0ce43c0 commit 81f6073
Show file tree
Hide file tree
Showing 55 changed files with 3,225 additions and 885 deletions.
17 changes: 17 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ include:
- /deps-rocm.yaml
- /deps-vcpkg.yaml
- /deps-windows.yaml
- /deps-compiler-acceleration.yaml
- /gpus-rocm.yaml
- /rules.yaml

Expand Down Expand Up @@ -68,10 +69,12 @@ copyright-date:
- .deps:rocm
- .deps:cmake-minimum
- .deps:vcpkg
- .deps:compiler-acceleration
before_script:
- !reference [".deps:rocm", before_script]
- !reference [".deps:cmake-minimum", before_script]
- !reference [".deps:vcpkg", before_script]
- !reference [".deps:compiler-acceleration", before_script]
- $VCPKG_DIR/vcpkg install
gtest
benchmark
Expand All @@ -80,9 +83,11 @@ copyright-date:
extends:
- .deps:rocm
- .deps:cmake-minimum
- .deps:compiler-acceleration
before_script:
- !reference [".deps:rocm", before_script]
- !reference [".deps:cmake-minimum", before_script]
- !reference [".deps:compiler-acceleration", before_script]
- $SUDO_CMD apt-get install -y -qq
libgtest-dev
libbenchmark-dev
Expand All @@ -107,6 +112,8 @@ copyright-date:
-D BUILD_BENCHMARK=ON
-D GPU_TARGETS=$GPU_TARGETS
-D AMDGPU_TEST_TARGETS=$GPU_TARGETS
-D CMAKE_C_COMPILER_LAUNCHER=phc_sccache_c
-D CMAKE_CXX_COMPILER_LAUNCHER=phc_sccache_cxx
-S $CI_PROJECT_DIR
-B $BUILD_DIR
- cmake
Expand All @@ -131,17 +138,21 @@ build:cmake-minimum-apt:
extends:
- .deps:rocm
- .deps:cmake-latest
- .deps:compiler-acceleration
before_script:
- !reference [".deps:rocm", before_script]
- !reference [".deps:cmake-latest", before_script]
- !reference [".deps:compiler-acceleration", before_script]

.cmake-minimum:
extends:
- .deps:rocm
- .deps:cmake-minimum
- .deps:compiler-acceleration
before_script:
- !reference [".deps:rocm", before_script]
- !reference [".deps:cmake-minimum", before_script]
- !reference [".deps:compiler-acceleration", before_script]

.build:common:
stage: build
Expand All @@ -166,6 +177,8 @@ build:cmake-minimum-apt:
-D CMAKE_CXX_FLAGS="-Wall -Wextra -Werror $EXTRA_CMAKE_CXX_FLAGS"
-D CMAKE_BUILD_TYPE="$BUILD_TYPE"
-D BUILD_$BUILD_TARGET=ON
-D CMAKE_C_COMPILER_LAUNCHER=phc_sccache_c
-D CMAKE_CXX_COMPILER_LAUNCHER=phc_sccache_cxx
-D BUILD_EXAMPLE=ON
-D GPU_TARGETS=$GPU_TARGETS
-D AMDGPU_TEST_TARGETS=$GPU_TARGETS
Expand Down Expand Up @@ -299,6 +312,8 @@ autotune:build:
-D BUILD_BENCHMARK=ON
-D BENCHMARK_CONFIG_TUNING=ON
-D GPU_TARGETS=$GPU_TARGETS
-D CMAKE_C_COMPILER_LAUNCHER=phc_sccache_c
-D CMAKE_CXX_COMPILER_LAUNCHER=phc_sccache_cxx
- cmake --build . --target $BENCHMARK_TARGETS
- 'rm -rf $BUILD_DIR/benchmark/benchmark*.parallel'
# The autotune benchmarks get very large, above GitLabs upload limit. Fortunately they compress well.
Expand Down Expand Up @@ -450,6 +465,7 @@ benchmark:
variables:
BENCHMARK_FILENAME_REGEX: ^benchmark
BENCHMARK_ALGORITHM_REGEX: ""
BENCHMARK_SEED: random
script:
- 'printf "CI Variables used in benchmarks:\nBENCHMARK_RESULT_DIR: %s\nBENCHMARK_FILENAME_REGEX: %s\nBENCHMARK_ALGORITHM_REGEX: %s \n" "$BENCHMARK_RESULT_DIR" "$BENCHMARK_FILENAME_REGEX" "$BENCHMARK_ALGORITHM_REGEX"'
- cd "${CI_PROJECT_DIR}"
Expand All @@ -461,6 +477,7 @@ benchmark:
--benchmark_output_dir "${BENCHMARK_RESULT_DIR}"
--benchmark_filename_regex "${BENCHMARK_FILENAME_REGEX}"
--benchmark_filter_regex "${BENCHMARK_ALGORITHM_REGEX}"
--seed "${BENCHMARK_SEED}"
artifacts:
paths:
- ${BENCHMARK_RESULT_DIR}
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@
Documentation for rocPRIM is available at
[https://rocm.docs.amd.com/projects/rocPRIM/en/latest/](https://rocm.docs.amd.com/projects/rocPRIM/en/latest/).

## (Unreleased) rocPRIM 3.4.0 for ROCm 6.4.0

### Added

* Added the parallel `find_first_of` device function with autotuned configurations, this function is similar to `std::find_first_of`, it searches for the first occurrence of any of the provided elements.

### Changed

### Resolved issues

* Fixed an issue where `rocprim::partial_sort_copy` would yield a compile error if the input iterator is const.
* Fixed incorrect 128-bit signed and unsigned integers type traits.
* Fixed compilation issue when `rocprim::radix_key_codec<...>` is specialized with a 128-bit integer.

### Upcoming changes

## (Unreleased) rocPRIM-3.3.0 for ROCm 6.3.0

### Added
Expand All @@ -15,6 +31,7 @@ Documentation for rocPRIM is available at
* Added a parallel `nth_element` device function similar to `std::nth_element`, this function rearranges elements smaller than the n-th before and bigger than the n-th after the n-th element.
* Added deterministic (bitwise reproducible) algorithm variants `rocprim::deterministic_inclusive_scan`, `rocprim::deterministic_exclusive_scan`, `rocprim::deterministic_inclusive_scan_by_key`, `rocprim::deterministic_exclusive_scan_by_key`, and `rocprim::deterministic_reduce_by_key`. These provide run-to-run stable results with non-associative operators such as float operations, at the cost of reduced performance.
* Added a parallel `partial_sort` and `partial_sort_copy` device function similar to `std::partial_sort` and `std::partial_sort_copy`, these functions rearranges elements such that the elements are the same as a sorted list up to and including the middle index.
* Added support of sizes larger than 2^32 in `device_merge_sort`.

### Changed

Expand Down
1 change: 1 addition & 0 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ add_rocprim_benchmark(benchmark_config_dispatch.cpp)
add_rocprim_benchmark(benchmark_device_adjacent_difference.cpp)
add_rocprim_benchmark(benchmark_device_batch_memcpy.cpp)
add_rocprim_benchmark(benchmark_device_binary_search.cpp)
add_rocprim_benchmark(benchmark_device_find_first_of.cpp)
add_rocprim_benchmark(benchmark_device_histogram.cpp)
add_rocprim_benchmark(benchmark_device_merge.cpp)
add_rocprim_benchmark(benchmark_device_merge_sort.cpp)
Expand Down
4 changes: 4 additions & 0 deletions benchmark/ConfigAutotuneSettings.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,9 @@ DataType;BlockSize;" PARENT_SCOPE)
set(list_across_names "KeyType;ValueType;BlockSize;TilesPerBlock" PARENT_SCOPE)
set(list_across "${LIMITED_TUNING_TYPES};${TUNING_TYPES};128 192 256 384 512;1 2" PARENT_SCOPE)
set(output_pattern_suffix "@KeyType@_@ValueType@_@BlockSize@_@TilesPerBlock@" PARENT_SCOPE)
elseif(file STREQUAL "benchmark_device_find_first_of")
set(list_across_names "DataType;BlockSize" PARENT_SCOPE)
set(list_across "${LIMITED_TUNING_TYPES};32 64 128 256 512 1024" PARENT_SCOPE)
set(output_pattern_suffix "@DataType@_@BlockSize@" PARENT_SCOPE)
endif()
endfunction()
150 changes: 150 additions & 0 deletions benchmark/benchmark_device_find_first_of.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// MIT License
//
// Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "benchmark_device_find_first_of.parallel.hpp"
#include "benchmark_utils.hpp"

// CmdParser
#include "cmdparser.hpp"

// Google Benchmark
#include <benchmark/benchmark.h>

// HIP API
#include <hip/hip_runtime.h>

#include <cstddef>
#include <string>

#ifndef DEFAULT_BYTES
constexpr size_t DEFAULT_BYTES = size_t{1} << 27; // 128 MiB
#endif

#define CREATE_BENCHMARK_FIND_FIRST_OF(TYPE, KEYS_SIZE, FIRST_OCCURENCE) \
{ \
const device_find_first_of_benchmark<TYPE> instance(KEYS_SIZE, FIRST_OCCURENCE); \
REGISTER_BENCHMARK(benchmarks, size, seed, stream, instance); \
}

// clang-format off
#define CREATE_BENCHMARK0(TYPE, KEYS_SIZE) \
{ \
CREATE_BENCHMARK_FIND_FIRST_OF(TYPE, KEYS_SIZE, 0.1) \
CREATE_BENCHMARK_FIND_FIRST_OF(TYPE, KEYS_SIZE, 0.5) \
CREATE_BENCHMARK_FIND_FIRST_OF(TYPE, KEYS_SIZE, 1.0) \
}

#define CREATE_BENCHMARK(TYPE) \
{ \
CREATE_BENCHMARK0(TYPE, 1) \
CREATE_BENCHMARK0(TYPE, 10) \
CREATE_BENCHMARK0(TYPE, 100) \
CREATE_BENCHMARK0(TYPE, 1000) \
CREATE_BENCHMARK0(TYPE, 10000) \
}
// clang-format on

int main(int argc, char* argv[])
{
cli::Parser parser(argc, argv);
parser.set_optional<size_t>("size", "size", DEFAULT_BYTES, "number of bytes");
parser.set_optional<int>("trials", "trials", -1, "number of iterations");
parser.set_optional<std::string>("name_format",
"name_format",
"human",
"either: json,human,txt");
parser.set_optional<std::string>("seed", "seed", "random", get_seed_message());
#ifdef BENCHMARK_CONFIG_TUNING
// optionally run an evenly split subset of benchmarks, when making multiple program invocations
parser.set_optional<int>("parallel_instance",
"parallel_instance",
0,
"parallel instance index");
parser.set_optional<int>("parallel_instances",
"parallel_instances",
1,
"total parallel instances");
#endif
parser.run_and_exit_if_error();

// Parse argv
benchmark::Initialize(&argc, argv);
const size_t size = parser.get<size_t>("size");
const int trials = parser.get<int>("trials");
bench_naming::set_format(parser.get<std::string>("name_format"));
const std::string seed_type = parser.get<std::string>("seed");
const managed_seed seed(seed_type);

// HIP
hipStream_t stream = 0; // default

// Benchmark info
add_common_benchmark_info();
benchmark::AddCustomContext("size", std::to_string(size));
benchmark::AddCustomContext("seed", seed_type);

// Add benchmarks
std::vector<benchmark::internal::Benchmark*> benchmarks{};
#ifdef BENCHMARK_CONFIG_TUNING
const int parallel_instance = parser.get<int>("parallel_instance");
const int parallel_instances = parser.get<int>("parallel_instances");
config_autotune_register::register_benchmark_subset(benchmarks,
parallel_instance,
parallel_instances,
size,
seed,
stream);
#else // BENCHMARK_CONFIG_TUNING
CREATE_BENCHMARK(int8_t)
CREATE_BENCHMARK(int16_t)
CREATE_BENCHMARK(int32_t)
CREATE_BENCHMARK(float)
CREATE_BENCHMARK(int64_t)
CREATE_BENCHMARK(double)

using custom_int2 = custom_type<int, int>;
using custom_longlong_double = custom_type<long long, double>;

CREATE_BENCHMARK(custom_int2)
CREATE_BENCHMARK(custom_longlong_double)
#endif // BENCHMARK_CONFIG_TUNING

// Use manual timing
for(auto& b : benchmarks)
{
b->UseManualTime();
b->Unit(benchmark::kMillisecond);
}

// Force number of iterations
if(trials > 0)
{
for(auto& b : benchmarks)
{
b->Iterations(trials);
}
}

// Run benchmarks
benchmark::RunSpecifiedBenchmarks();
return 0;
}
30 changes: 30 additions & 0 deletions benchmark/benchmark_device_find_first_of.parallel.cpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// MIT License
//
// Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "benchmark_device_find_first_of.parallel.hpp"
#include "benchmark_utils.hpp"

namespace
{
auto benchmarks = config_autotune_register::create_bulk(
device_find_first_of_benchmark_generator<@DataType@, @BlockSize@>::create);
} // namespace
Loading

0 comments on commit 81f6073

Please sign in to comment.