From 15bab39798c9d1c73b8276169ce20523ab8d805a Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Mon, 2 Dec 2024 11:45:21 +0200 Subject: [PATCH 01/12] initial version of InlineVector --- src/include/miopen/inline_vector.hpp | 97 ++++++++++++++++++++ test/gtest/inline_vector_basic_ops.cpp | 121 +++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 src/include/miopen/inline_vector.hpp create mode 100644 test/gtest/inline_vector_basic_ops.cpp diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp new file mode 100644 index 0000000000..193c0a2b98 --- /dev/null +++ b/src/include/miopen/inline_vector.hpp @@ -0,0 +1,97 @@ +/******************************************************************************* + * + * MIT License + * + * Copyright (c) 2024 Advanced Micro Devices, Inc. + * + * 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. + * + *******************************************************************************/ +#ifndef GUARD_MIOPEN_INLINE_VECTOR_HPP +#define GUARD_MIOPEN_INLINE_VECTOR_HPP + +#include +#include +#include + +namespace miopen { + +template +class InlineVector +{ +public: + using value_type = T; + + InlineVector() noexcept : real_size(0){}; + + InlineVector(const InlineVector& inline_vec) = default; + InlineVector(InlineVector&& inline_vec) noexcept = default; + + InlineVector(std::initializer_list _data) : real_size(_data.size()) + { + if(_data.size() > N) + { + MIOPEN_THROW("Input data size is bigger than InlineVector's capacity"); + } + std::copy(_data.begin(), _data.end(), data.begin()); + } + + template > + InlineVector(_InputIterator first, _InputIterator last) + { + if(std::distance(first, last) > N) + { + MIOPEN_THROW("Input data size is bigger than InlineVector's capacity"); + } + std::copy(first, last, data.begin()); + real_size = std::distance(first, last); + } + + // Iterators + T* begin() { return data.begin(); } + + T* end() { return (data.begin() + real_size); } + + // Reverse iterators + std::reverse_iterator rbegin() { return std::reverse_iterator(end()); } + + std::reverse_iterator rend() { return std::reverse_iterator(begin()); } + + // Element access + T& operator[](std::size_t n) { return data[n]; } + + const T& operator[](std::size_t n) const { return data[n]; } + + // Empty + bool empty() const { return real_size == 0; } + + // Real size + uint8_t size() const { return real_size; } + + // Capacity + constexpr uint8_t capacity() const { return N; } + +private: + std::array data; + uint8_t real_size; +}; + +} // namespace miopen + +#endif diff --git a/test/gtest/inline_vector_basic_ops.cpp b/test/gtest/inline_vector_basic_ops.cpp new file mode 100644 index 0000000000..2142fc1ea1 --- /dev/null +++ b/test/gtest/inline_vector_basic_ops.cpp @@ -0,0 +1,121 @@ +/******************************************************************************* + * + * MIT License + * + * Copyright (c) 2024 Advanced Micro Devices, Inc. + * + * 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 + +#include + +#include +#include + +namespace { + +TEST(CPU_InlineVectorSizeAndAccumulate_NONE, Test) +{ + miopen::InlineVector in_v1{4, 2, 1}; + std::vector v1{4, 2, 1}; + + EXPECT_EQ(in_v1.size(), v1.size()); + + for(uint8_t i = 0; i < in_v1.size(); i++) + { + EXPECT_EQ(in_v1[i], v1[i]); + } + + int sum_in_v1 = std::accumulate(in_v1.begin(), in_v1.end(), 0); + int sum_v1 = std::accumulate(v1.begin(), v1.end(), 0); + + EXPECT_EQ(sum_in_v1, sum_v1); +} + +TEST(CPU_InlineVectorFindIfAndDistance_NONE, Test) +{ + std::initializer_list init_list_2{4, 1, 2, 2}; + miopen::InlineVector in_v2 = init_list_2; + std::vector v2 = init_list_2; + + auto first_not_one_in_v2 = + std::find_if(in_v2.rbegin(), in_v2.rend(), [](int i) { return i != 1; }); + auto first_note_one_v2 = std::find_if(v2.rbegin(), v2.rend(), [](int i) { return i != 1; }); + EXPECT_EQ(*first_not_one_in_v2, *first_note_one_v2); + + auto d_in_v2 = std::distance(in_v2.begin(), first_not_one_in_v2.base()); + auto d_v2 = std::distance(v2.begin(), first_note_one_v2.base()); + EXPECT_EQ(d_in_v2, d_v2); +} + +TEST(CPU_InlineVecotrTie_NONE, Test) +{ + std::initializer_list init_list_3{4, 1, 2, 2}; + miopen::InlineVector in_v3 = init_list_3; + std::vector v3 = init_list_3; + + std::array arr_in_v3; + std::array arr_v3; + std::tie(arr_in_v3[0], arr_in_v3[1], arr_in_v3[2], arr_in_v3[3]) = miopen::tien<4>(in_v3); + std::tie(arr_v3[0], arr_v3[1], arr_v3[2], arr_v3[3]) = miopen::tien<4>(v3); + + for(uint8_t i = 0; i < in_v3.size(); i++) + { + EXPECT_EQ(arr_in_v3[i], arr_v3[i]); + } +} + +TEST(CPU_InlineVectorCapacityAndEmpty_NONE, Test) +{ + miopen::InlineVector in_v4{}; + std::vector v4{}; + + ASSERT_EQ(in_v4.capacity(), 5); + + EXPECT_EQ(in_v4.empty(), v4.empty()); + EXPECT_EQ(in_v4.begin(), in_v4.end()); +} + +TEST(CPU_InlineVectorIteratorsConstructor_NONE, Test) +{ + std::vector vv = {1, 2, 4, 1}; + miopen::InlineVector in_v5(vv.begin(), vv.end()); + std::vector v5(vv.begin(), vv.end()); + + for(uint8_t i = 0; i < in_v5.size(); i++) + { + EXPECT_EQ(in_v5[i], v5[i]); + } +} + +TEST(CPU_InlineVectorConstructorException_NONE, Test) +{ + std::initializer_list init_list_v6{1, 2, 3, 4, 5, 6}; + auto constructor_1 = [init_list_v6]() { + miopen::InlineVector v6(init_list_v6.begin(), init_list_v6.end()); + }; + auto constructor_2 = [init_list_v6]() { miopen::InlineVector v6(init_list_v6); }; + ASSERT_ANY_THROW(constructor_1()); + ASSERT_ANY_THROW(constructor_2()); +} + +} // namespace From 87d4faf1ee6fa0bf1fd857bee17ec62cbec24da3 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Mon, 2 Dec 2024 16:39:13 +0200 Subject: [PATCH 02/12] added additional methods --- src/include/miopen/inline_vector.hpp | 217 ++++++++++++++++++++++--- test/gtest/inline_vector_basic_ops.cpp | 94 ++++++++++- 2 files changed, 287 insertions(+), 24 deletions(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index 193c0a2b98..0a58b017d1 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -32,64 +32,241 @@ namespace miopen { -template +template class InlineVector { public: using value_type = T; - InlineVector() noexcept : real_size(0){}; + // Default constructor + InlineVector() : real_size(0) + { + if(!std::is_scalar_v) + { + MIOPEN_THROW("InlineVector support only scalar values for now"); + } + }; + // Copy and move constructor InlineVector(const InlineVector& inline_vec) = default; InlineVector(InlineVector&& inline_vec) noexcept = default; - InlineVector(std::initializer_list _data) : real_size(_data.size()) + InlineVector(std::initializer_list __data) : real_size(__data.size()) { - if(_data.size() > N) + if(real_size > N) { MIOPEN_THROW("Input data size is bigger than InlineVector's capacity"); } - std::copy(_data.begin(), _data.end(), data.begin()); + + if(!std::is_scalar_v) + { + MIOPEN_THROW("InlineVector support only scalar values for now"); + } + + std::copy(__data.begin(), __data.end(), _data.begin()); } template > - InlineVector(_InputIterator first, _InputIterator last) + InlineVector(_InputIterator first, _InputIterator last) : real_size(std::distance(first, last)) { - if(std::distance(first, last) > N) + if(real_size > N) { MIOPEN_THROW("Input data size is bigger than InlineVector's capacity"); } - std::copy(first, last, data.begin()); - real_size = std::distance(first, last); + + if(!std::is_scalar_v) + { + MIOPEN_THROW("InlineVector support only scalar values for now"); + } + + std::copy(first, last, _data.begin()); } + // Copy/move operator + InlineVector& operator=(const InlineVector& inline_vec) = default; + InlineVector& operator=(InlineVector&& inline_vec) noexcept = default; + // Iterators - T* begin() { return data.begin(); } + T* begin() noexcept { return _data.begin(); } - T* end() { return (data.begin() + real_size); } + const T* begin() const noexcept { return _data.begin(); } + + T* end() noexcept { return (_data.begin() + real_size); } + + const T* end() const noexcept { return (_data.begin() + real_size); } + + // Constant iterator + const T* cbegin() const noexcept { return _data.cbegin(); } + + const T* cend() const noexcept { return (_data.cbegin() + real_size); } // Reverse iterators - std::reverse_iterator rbegin() { return std::reverse_iterator(end()); } + std::reverse_iterator rbegin() noexcept { return std::reverse_iterator(end()); } + + std::reverse_iterator rbegin() const noexcept + { + return std::reverse_iterator(end()); + } + + std::reverse_iterator rend() noexcept { return std::reverse_iterator(begin()); } + + std::reverse_iterator rend() const noexcept + { + return std::reverse_iterator(begin()); + } - std::reverse_iterator rend() { return std::reverse_iterator(begin()); } + // Constant reverse iterators + std::reverse_iterator crbegin() const noexcept + { + return std::reverse_iterator(cend()); + } + + std::reverse_iterator crend() const noexcept + { + return std::reverse_iterator(cbegin()); + } // Element access - T& operator[](std::size_t n) { return data[n]; } + T& operator[](std::size_t n) noexcept { return _data[n]; } + + const T& operator[](std::size_t n) const noexcept { return _data[n]; } + + // Element access with boundaries check + T& at(std::size_t n) + { + if(n >= real_size) + { + MIOPEN_THROW("Access to InlineVector is out of range"); + } + return _data.at(n); + } + + const T& at(std::size_t n) const + { + if(n >= real_size) + { + MIOPEN_THROW("Access to InlineVector is out of range"); + } + return _data.at(n); + } + + // Access to first element + T& front() + { + if(empty()) + { + MIOPEN_THROW("Cannot get front element, InlineVector is empty"); + } + return (*begin()); + } + + const T& front() const + { + if(empty()) + { + MIOPEN_THROW("Cannot get front element, InlineVector is empty"); + } + return (*begin()); + } + + // Access to last element + T& back() + { + if(empty()) + { + MIOPEN_THROW("Cannot get back element, InlineVector is empty"); + } + return *(end() - 1); + } + + const T& back() const + { + if(empty()) + { + MIOPEN_THROW("Cannot get back element, InlineVector is empty"); + } + return *(end() - 1); + } + + // Pointer to start of array + T* data() noexcept { return _data.data(); } + + const T* data() const noexcept { return _data.data(); } + + // Resize + void resize(std::size_t n) + { + if(n > N) + { + MIOPEN_THROW("It is not possible to resize beyond capacity"); + } + + real_size = n; + } + + void resize(std::size_t n, const T& v) + { + if(n > N) + { + MIOPEN_THROW("It is not possible to resize beyond capacity"); + } + + if(n > real_size) + { + std::fill(begin() + real_size, begin() + n, v); + } + + real_size = n; + } + + // Add element to the back + void push_back(const T& e) + { + if(real_size == N) + { + MIOPEN_THROW("InlineVector already full"); + } + _data[real_size++] = e; + } + + void push_back(const T&& e) + { + if(real_size == N) + { + MIOPEN_THROW("InlineVector already full"); + } + _data[real_size++] = std::move(e); + } + + // Create element and add it to the back + template + void emplace_back(_Args&&... args) + { + if(real_size == N) + { + MIOPEN_THROW("InlineVector already full"); + } + _data[real_size++] = T(std::forward<_Args>(args)...); + } + + // Remove element from the back + void pop_back() noexcept { real_size = ((real_size - 1) >= 0) ? (real_size - 1) : 0; } - const T& operator[](std::size_t n) const { return data[n]; } + // Clear + constexpr void clear() noexcept { real_size = 0; } // Empty - bool empty() const { return real_size == 0; } + bool empty() const noexcept { return real_size == 0; } // Real size - uint8_t size() const { return real_size; } + std::size_t size() const noexcept { return real_size; } // Capacity - constexpr uint8_t capacity() const { return N; } + constexpr std::size_t capacity() const { return N; } private: - std::array data; - uint8_t real_size; + std::array _data{}; + std::size_t real_size; }; } // namespace miopen diff --git a/test/gtest/inline_vector_basic_ops.cpp b/test/gtest/inline_vector_basic_ops.cpp index 2142fc1ea1..911820d2f3 100644 --- a/test/gtest/inline_vector_basic_ops.cpp +++ b/test/gtest/inline_vector_basic_ops.cpp @@ -35,8 +35,8 @@ namespace { TEST(CPU_InlineVectorSizeAndAccumulate_NONE, Test) { - miopen::InlineVector in_v1{4, 2, 1}; - std::vector v1{4, 2, 1}; + miopen::InlineVector in_v1{4, 2, 1}; + std::vector v1{4, 2, 1}; EXPECT_EQ(in_v1.size(), v1.size()); @@ -60,11 +60,12 @@ TEST(CPU_InlineVectorFindIfAndDistance_NONE, Test) auto first_not_one_in_v2 = std::find_if(in_v2.rbegin(), in_v2.rend(), [](int i) { return i != 1; }); auto first_note_one_v2 = std::find_if(v2.rbegin(), v2.rend(), [](int i) { return i != 1; }); - EXPECT_EQ(*first_not_one_in_v2, *first_note_one_v2); auto d_in_v2 = std::distance(in_v2.begin(), first_not_one_in_v2.base()); auto d_v2 = std::distance(v2.begin(), first_note_one_v2.base()); - EXPECT_EQ(d_in_v2, d_v2); + + ASSERT_EQ(d_in_v2, d_v2); + EXPECT_EQ(*first_not_one_in_v2, *first_note_one_v2); } TEST(CPU_InlineVecotrTie_NONE, Test) @@ -118,4 +119,89 @@ TEST(CPU_InlineVectorConstructorException_NONE, Test) ASSERT_ANY_THROW(constructor_2()); } +TEST(CPU_InlineVectorAllOf_NONE, Test) +{ + miopen::InlineVector in_v7({3, 1, 1}); + std::vector v7{3, 2, 1}; + + bool all_of_in_v7 = std::all_of(in_v7.cbegin(), in_v7.cend(), [](size_t x) { return x > 0; }); + bool all_of_v7 = std::all_of(v7.cbegin(), v7.cend(), [](size_t x) { return x > 0; }); + + EXPECT_EQ(all_of_in_v7, all_of_v7); +} + +TEST(CPU_InlineVectorResize_NONE, Test) +{ + miopen::InlineVector in_v8({2, 2, 2, 2, 2}); + in_v8.resize(2); + + EXPECT_EQ(in_v8.size(), 2); + + in_v8.resize(4, 1); + + std::vector v8{2, 2, 1, 1}; + + EXPECT_EQ(in_v8.size(), v8.size()); + + for(uint8_t i = 0; i < in_v8.size(); i++) + { + EXPECT_EQ(in_v8[i], v8[i]); + } +} + +TEST(CPU_InlineVectorPushBackPopBack_NONE, Test) +{ + miopen::InlineVector in_v9 = {8, 7, 6}; + std::vector v9{8, 7, 6, 5}; + + in_v9.push_back(5); + + EXPECT_EQ(in_v9.size(), v9.size()); + for(uint8_t i = 0; i < in_v9.size(); i++) + { + EXPECT_EQ(in_v9[i], v9[i]); + } + + v9.pop_back(); + in_v9.pop_back(); + + EXPECT_EQ(in_v9.size(), v9.size()); + for(uint8_t i = 0; i < in_v9.size(); i++) + { + EXPECT_EQ(in_v9[i], v9[i]); + } + + in_v9.push_back(5); + in_v9.push_back(4); + EXPECT_ANY_THROW({ in_v9.push_back(3); }); +} + +TEST(CPU_InlineVectorAt_NONE, Test) +{ + miopen::InlineVector in_v10{2, 4, 6}; + std::vector v10{2, 4, 6}; + + EXPECT_ANY_THROW(in_v10.at(3)); + EXPECT_ANY_THROW(in_v10.at(5)); + EXPECT_EQ(in_v10.at(1), v10.at(1)); +} + +TEST(CPU_InlineVectorFrontBack_NONE, Test) +{ + miopen::InlineVector in_v11{}; + + EXPECT_ANY_THROW(in_v11.front()); + EXPECT_ANY_THROW(in_v11.back()); + + in_v11.push_back(10); + EXPECT_EQ(in_v11.front(), in_v11.back()); +} + +TEST(CPU_InlineVectorClear_NONE, Test) +{ + miopen::InlineVector in_v12{1, 2, 3, 4, 5}; + in_v12.clear(); + EXPECT_EQ(in_v12.size(), 0); +} + } // namespace From 740ba1a171abf9973ba3c7ed88b2fea9e15687e1 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Tue, 3 Dec 2024 09:54:44 +0200 Subject: [PATCH 03/12] minor changes --- src/include/miopen/inline_vector.hpp | 43 +++++++--------------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index 0a58b017d1..4172fc1bcf 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -37,15 +37,10 @@ class InlineVector { public: using value_type = T; + static_assert(std::is_scalar_v, "Input data size is bigger than InlineVector's capacity"); // Default constructor - InlineVector() : real_size(0) - { - if(!std::is_scalar_v) - { - MIOPEN_THROW("InlineVector support only scalar values for now"); - } - }; + InlineVector() = default; // Copy and move constructor InlineVector(const InlineVector& inline_vec) = default; @@ -58,11 +53,6 @@ class InlineVector MIOPEN_THROW("Input data size is bigger than InlineVector's capacity"); } - if(!std::is_scalar_v) - { - MIOPEN_THROW("InlineVector support only scalar values for now"); - } - std::copy(__data.begin(), __data.end(), _data.begin()); } @@ -74,11 +64,6 @@ class InlineVector MIOPEN_THROW("Input data size is bigger than InlineVector's capacity"); } - if(!std::is_scalar_v) - { - MIOPEN_THROW("InlineVector support only scalar values for now"); - } - std::copy(first, last, _data.begin()); } @@ -96,9 +81,9 @@ class InlineVector const T* end() const noexcept { return (_data.begin() + real_size); } // Constant iterator - const T* cbegin() const noexcept { return _data.cbegin(); } + const T* cbegin() const noexcept { return begin(); } - const T* cend() const noexcept { return (_data.cbegin() + real_size); } + const T* cend() const noexcept { return end(); } // Reverse iterators std::reverse_iterator rbegin() noexcept { return std::reverse_iterator(end()); } @@ -176,7 +161,7 @@ class InlineVector { MIOPEN_THROW("Cannot get back element, InlineVector is empty"); } - return *(end() - 1); + return *std::prev(end()); } const T& back() const @@ -185,7 +170,7 @@ class InlineVector { MIOPEN_THROW("Cannot get back element, InlineVector is empty"); } - return *(end() - 1); + return *std::prev(end()); } // Pointer to start of array @@ -194,15 +179,7 @@ class InlineVector const T* data() const noexcept { return _data.data(); } // Resize - void resize(std::size_t n) - { - if(n > N) - { - MIOPEN_THROW("It is not possible to resize beyond capacity"); - } - - real_size = n; - } + void resize(std::size_t n) { resize(n, T{}); } void resize(std::size_t n, const T& v) { @@ -250,10 +227,10 @@ class InlineVector } // Remove element from the back - void pop_back() noexcept { real_size = ((real_size - 1) >= 0) ? (real_size - 1) : 0; } + void pop_back() noexcept { real_size = (real_size > 1) ? (real_size - 1) : 0; } // Clear - constexpr void clear() noexcept { real_size = 0; } + void clear() noexcept { real_size = 0; } // Empty bool empty() const noexcept { return real_size == 0; } @@ -266,7 +243,7 @@ class InlineVector private: std::array _data{}; - std::size_t real_size; + std::size_t real_size = 0; }; } // namespace miopen From bf3baff9f23ab90b6139947c7129256b3f8c2fa5 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Tue, 3 Dec 2024 13:46:43 +0200 Subject: [PATCH 04/12] fix for windows build --- src/include/miopen/inline_vector.hpp | 66 ++++++++++++++++------------ 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index 4172fc1bcf..5fadbf36ff 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -36,7 +36,17 @@ template class InlineVector { public: - using value_type = T; + using storage_type = std::array; + using value_type = storage_type::value_type; + using size_type = storage_type::size_type; + using reference = storage_type::reference; + using const_reference = storage_type::const_reference; + using pointer = storage_type::pointer; + using const_pointer = storage_type::const_pointer; + using iterator = storage_type::iterator; + using const_iterator = storage_type::const_iterator; + using reverse_iterator = storage_type::reverse_iterator; + using const_reverse_iterator = storage_type::const_reverse_iterator; static_assert(std::is_scalar_v, "Input data size is bigger than InlineVector's capacity"); // Default constructor @@ -68,56 +78,56 @@ class InlineVector } // Copy/move operator - InlineVector& operator=(const InlineVector& inline_vec) = default; + InlineVector& operator=(const InlineVector& inline_vec) = default; InlineVector& operator=(InlineVector&& inline_vec) noexcept = default; // Iterators - T* begin() noexcept { return _data.begin(); } + iterator begin() noexcept { return _data.begin(); } - const T* begin() const noexcept { return _data.begin(); } + const_iterator begin() const noexcept { return _data.begin(); } - T* end() noexcept { return (_data.begin() + real_size); } + iterator end() noexcept { return (_data.begin() + real_size); } - const T* end() const noexcept { return (_data.begin() + real_size); } + const_iterator end() const noexcept { return (_data.begin() + real_size); } // Constant iterator - const T* cbegin() const noexcept { return begin(); } + const_iterator cbegin() const noexcept { return begin(); } - const T* cend() const noexcept { return end(); } + const_iterator cend() const noexcept { return end(); } // Reverse iterators - std::reverse_iterator rbegin() noexcept { return std::reverse_iterator(end()); } + reverse_iterator rbegin() noexcept { return std::reverse_iterator(end()); } - std::reverse_iterator rbegin() const noexcept + const_reverse_iterator rbegin() const noexcept { return std::reverse_iterator(end()); } - std::reverse_iterator rend() noexcept { return std::reverse_iterator(begin()); } + reverse_iterator rend() noexcept { return std::reverse_iterator(begin()); } - std::reverse_iterator rend() const noexcept + const_reverse_iterator rend() const noexcept { return std::reverse_iterator(begin()); } // Constant reverse iterators - std::reverse_iterator crbegin() const noexcept + const_reverse_iterator crbegin() const noexcept { return std::reverse_iterator(cend()); } - std::reverse_iterator crend() const noexcept + const_reverse_iterator crend() const noexcept { return std::reverse_iterator(cbegin()); } // Element access - T& operator[](std::size_t n) noexcept { return _data[n]; } + reference operator[](std::size_t n) noexcept { return _data[n]; } - const T& operator[](std::size_t n) const noexcept { return _data[n]; } + const_reference operator[](std::size_t n) const noexcept { return _data[n]; } // Element access with boundaries check - T& at(std::size_t n) + reference at(std::size_t n) { if(n >= real_size) { @@ -126,7 +136,7 @@ class InlineVector return _data.at(n); } - const T& at(std::size_t n) const + const_reference at(std::size_t n) const { if(n >= real_size) { @@ -136,7 +146,7 @@ class InlineVector } // Access to first element - T& front() + reference front() { if(empty()) { @@ -145,7 +155,7 @@ class InlineVector return (*begin()); } - const T& front() const + const_reference front() const { if(empty()) { @@ -155,7 +165,7 @@ class InlineVector } // Access to last element - T& back() + reference back() { if(empty()) { @@ -164,7 +174,7 @@ class InlineVector return *std::prev(end()); } - const T& back() const + const_reference back() const { if(empty()) { @@ -174,9 +184,9 @@ class InlineVector } // Pointer to start of array - T* data() noexcept { return _data.data(); } + pointer data() noexcept { return _data.data(); } - const T* data() const noexcept { return _data.data(); } + const_pointer data() const noexcept { return _data.data(); } // Resize void resize(std::size_t n) { resize(n, T{}); } @@ -236,14 +246,14 @@ class InlineVector bool empty() const noexcept { return real_size == 0; } // Real size - std::size_t size() const noexcept { return real_size; } + size_type size() const noexcept { return real_size; } // Capacity - constexpr std::size_t capacity() const { return N; } + constexpr size_type capacity() const { return N; } private: - std::array _data{}; - std::size_t real_size = 0; + storage_type _data{}; + size_type real_size = 0; }; } // namespace miopen From 08bfc9fc6f8734b7cc2242dc34415b001633b971 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Tue, 3 Dec 2024 14:32:26 +0200 Subject: [PATCH 05/12] fixed typo and change member name --- src/include/miopen/inline_vector.hpp | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index 5fadbf36ff..124e800d50 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -47,7 +47,7 @@ class InlineVector using const_iterator = storage_type::const_iterator; using reverse_iterator = storage_type::reverse_iterator; using const_reverse_iterator = storage_type::const_reverse_iterator; - static_assert(std::is_scalar_v, "Input data size is bigger than InlineVector's capacity"); + static_assert(std::is_scalar_v, "InlineVector currently supports scalar type only"); // Default constructor InlineVector() = default; @@ -56,14 +56,14 @@ class InlineVector InlineVector(const InlineVector& inline_vec) = default; InlineVector(InlineVector&& inline_vec) noexcept = default; - InlineVector(std::initializer_list __data) : real_size(__data.size()) + InlineVector(std::initializer_list data) : real_size(data.size()) { if(real_size > N) { MIOPEN_THROW("Input data size is bigger than InlineVector's capacity"); } - std::copy(__data.begin(), __data.end(), _data.begin()); + std::copy(data.begin(), data.end(), storage.begin()); } template > @@ -74,7 +74,7 @@ class InlineVector MIOPEN_THROW("Input data size is bigger than InlineVector's capacity"); } - std::copy(first, last, _data.begin()); + std::copy(first, last, storage.begin()); } // Copy/move operator @@ -82,13 +82,13 @@ class InlineVector InlineVector& operator=(InlineVector&& inline_vec) noexcept = default; // Iterators - iterator begin() noexcept { return _data.begin(); } + iterator begin() noexcept { return storage.begin(); } - const_iterator begin() const noexcept { return _data.begin(); } + const_iterator begin() const noexcept { return storage.begin(); } - iterator end() noexcept { return (_data.begin() + real_size); } + iterator end() noexcept { return (storage.begin() + real_size); } - const_iterator end() const noexcept { return (_data.begin() + real_size); } + const_iterator end() const noexcept { return (storage.begin() + real_size); } // Constant iterator const_iterator cbegin() const noexcept { return begin(); } @@ -122,9 +122,9 @@ class InlineVector } // Element access - reference operator[](std::size_t n) noexcept { return _data[n]; } + reference operator[](std::size_t n) noexcept { return storage[n]; } - const_reference operator[](std::size_t n) const noexcept { return _data[n]; } + const_reference operator[](std::size_t n) const noexcept { return storage[n]; } // Element access with boundaries check reference at(std::size_t n) @@ -133,7 +133,7 @@ class InlineVector { MIOPEN_THROW("Access to InlineVector is out of range"); } - return _data.at(n); + return storage.at(n); } const_reference at(std::size_t n) const @@ -142,7 +142,7 @@ class InlineVector { MIOPEN_THROW("Access to InlineVector is out of range"); } - return _data.at(n); + return storage.at(n); } // Access to first element @@ -184,9 +184,9 @@ class InlineVector } // Pointer to start of array - pointer data() noexcept { return _data.data(); } + pointer data() noexcept { return storage.data(); } - const_pointer data() const noexcept { return _data.data(); } + const_pointer data() const noexcept { return storage.data(); } // Resize void resize(std::size_t n) { resize(n, T{}); } @@ -213,7 +213,7 @@ class InlineVector { MIOPEN_THROW("InlineVector already full"); } - _data[real_size++] = e; + storage[real_size++] = e; } void push_back(const T&& e) @@ -222,7 +222,7 @@ class InlineVector { MIOPEN_THROW("InlineVector already full"); } - _data[real_size++] = std::move(e); + storage[real_size++] = std::move(e); } // Create element and add it to the back @@ -233,7 +233,7 @@ class InlineVector { MIOPEN_THROW("InlineVector already full"); } - _data[real_size++] = T(std::forward<_Args>(args)...); + storage[real_size++] = T(std::forward<_Args>(args)...); } // Remove element from the back @@ -252,7 +252,7 @@ class InlineVector constexpr size_type capacity() const { return N; } private: - storage_type _data{}; + storage_type storage{}; size_type real_size = 0; }; From 3c940b028a6066f7c36d3af1940272cb7ff03ea1 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Tue, 3 Dec 2024 17:24:08 +0200 Subject: [PATCH 06/12] more changes regarding windows build --- src/include/miopen/inline_vector.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index 124e800d50..7d81fec629 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -66,7 +66,7 @@ class InlineVector std::copy(data.begin(), data.end(), storage.begin()); } - template > + template InlineVector(_InputIterator first, _InputIterator last) : real_size(std::distance(first, last)) { if(real_size > N) From 570f3eb15be9a6ec3cbf9a5f2b8901a825f07509 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Wed, 4 Dec 2024 11:30:42 +0200 Subject: [PATCH 07/12] another try to fix windows build --- src/include/miopen/inline_vector.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index 7d81fec629..42b001eb9f 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -37,16 +37,16 @@ class InlineVector { public: using storage_type = std::array; - using value_type = storage_type::value_type; - using size_type = storage_type::size_type; - using reference = storage_type::reference; - using const_reference = storage_type::const_reference; - using pointer = storage_type::pointer; - using const_pointer = storage_type::const_pointer; - using iterator = storage_type::iterator; - using const_iterator = storage_type::const_iterator; - using reverse_iterator = storage_type::reverse_iterator; - using const_reverse_iterator = storage_type::const_reverse_iterator; + using value_type = typename storage_type::value_type; + using size_type = typename storage_type::size_type; + using reference = typename storage_type::reference; + using const_reference = typename storage_type::const_reference; + using pointer = typename storage_type::pointer; + using const_pointer = typename storage_type::const_pointer; + using iterator = typename storage_type::iterator; + using const_iterator = typename storage_type::const_iterator; + using reverse_iterator = typename storage_type::reverse_iterator; + using const_reverse_iterator = typename storage_type::const_reverse_iterator; static_assert(std::is_scalar_v, "InlineVector currently supports scalar type only"); // Default constructor From a7dd527eb2038038e828644d39c9b05d36dee8f9 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Wed, 4 Dec 2024 13:50:21 +0200 Subject: [PATCH 08/12] changes in template parameter names --- src/include/miopen/inline_vector.hpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index 42b001eb9f..f28cb97a28 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -66,8 +66,8 @@ class InlineVector std::copy(data.begin(), data.end(), storage.begin()); } - template - InlineVector(_InputIterator first, _InputIterator last) : real_size(std::distance(first, last)) + template + InlineVector(InputIterator first, InputIterator last) : real_size(std::distance(first, last)) { if(real_size > N) { @@ -122,9 +122,17 @@ class InlineVector } // Element access - reference operator[](std::size_t n) noexcept { return storage[n]; } + reference operator[](std::size_t n) + { + assert(n < N); + return storage[n]; + } - const_reference operator[](std::size_t n) const noexcept { return storage[n]; } + const_reference operator[](std::size_t n) const + { + assert(n < N); + return storage[n]; + } // Element access with boundaries check reference at(std::size_t n) @@ -226,14 +234,14 @@ class InlineVector } // Create element and add it to the back - template - void emplace_back(_Args&&... args) + template + void emplace_back(Args&&... args) { if(real_size == N) { MIOPEN_THROW("InlineVector already full"); } - storage[real_size++] = T(std::forward<_Args>(args)...); + storage[real_size++] = T(std::forward(args)...); } // Remove element from the back From a95bacbbeba566293436b7cb1b219d4c1a8e42cb Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Wed, 4 Dec 2024 15:11:38 +0200 Subject: [PATCH 09/12] imitating array implementation of all begin/end methods --- src/include/miopen/inline_vector.hpp | 40 ++++++++++------------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index f28cb97a28..f36be7e036 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -82,53 +82,41 @@ class InlineVector InlineVector& operator=(InlineVector&& inline_vec) noexcept = default; // Iterators - iterator begin() noexcept { return storage.begin(); } + iterator begin() noexcept { return iterator(data()); } - const_iterator begin() const noexcept { return storage.begin(); } + const_iterator begin() const noexcept { return const_iterator(data()); } - iterator end() noexcept { return (storage.begin() + real_size); } + iterator end() noexcept { return iterator(data() + real_size); } - const_iterator end() const noexcept { return (storage.begin() + real_size); } + const_iterator end() const noexcept { return const_iterator(data() + real_size); } // Constant iterator - const_iterator cbegin() const noexcept { return begin(); } + const_iterator cbegin() const noexcept { return const_iterator(data()); } - const_iterator cend() const noexcept { return end(); } + const_iterator cend() const noexcept { return const_iterator(data() + real_size); } // Reverse iterators - reverse_iterator rbegin() noexcept { return std::reverse_iterator(end()); } + reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const noexcept - { - return std::reverse_iterator(end()); - } + const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - reverse_iterator rend() noexcept { return std::reverse_iterator(begin()); } + reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - const_reverse_iterator rend() const noexcept - { - return std::reverse_iterator(begin()); - } + const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } // Constant reverse iterators - const_reverse_iterator crbegin() const noexcept - { - return std::reverse_iterator(cend()); - } + const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - const_reverse_iterator crend() const noexcept - { - return std::reverse_iterator(cbegin()); - } + const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } // Element access - reference operator[](std::size_t n) + reference operator[](std::size_t n) noexcept { assert(n < N); return storage[n]; } - const_reference operator[](std::size_t n) const + const_reference operator[](std::size_t n) const noexcept { assert(n < N); return storage[n]; From f8f5f0d99c13f5aeedb5335c38c1d4682e4cf9f3 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Wed, 4 Dec 2024 17:24:27 +0200 Subject: [PATCH 10/12] fix to pass cppcheck --- test/gtest/inline_vector_basic_ops.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/gtest/inline_vector_basic_ops.cpp b/test/gtest/inline_vector_basic_ops.cpp index 911820d2f3..1b10a4c222 100644 --- a/test/gtest/inline_vector_basic_ops.cpp +++ b/test/gtest/inline_vector_basic_ops.cpp @@ -25,14 +25,11 @@ *******************************************************************************/ #include - #include #include #include -namespace { - TEST(CPU_InlineVectorSizeAndAccumulate_NONE, Test) { miopen::InlineVector in_v1{4, 2, 1}; @@ -203,5 +200,3 @@ TEST(CPU_InlineVectorClear_NONE, Test) in_v12.clear(); EXPECT_EQ(in_v12.size(), 0); } - -} // namespace From 843c1dc37d7c0dc7952f7a9d1c809bda6843e5c6 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Thu, 5 Dec 2024 09:46:37 +0200 Subject: [PATCH 11/12] change in runtime assert --- src/include/miopen/inline_vector.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index f36be7e036..2fccf69fe9 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -112,13 +112,13 @@ class InlineVector // Element access reference operator[](std::size_t n) noexcept { - assert(n < N); + assert(n < real_size); return storage[n]; } const_reference operator[](std::size_t n) const noexcept { - assert(n < N); + assert(n < real_size); return storage[n]; } From 75e9e4295fca05fb5cc2be00a0eadd519bee4a92 Mon Sep 17 00:00:00 2001 From: novakovicdj Date: Thu, 5 Dec 2024 14:42:28 +0200 Subject: [PATCH 12/12] remove emplace_back and leave comment for further implementation of it --- src/include/miopen/inline_vector.hpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/include/miopen/inline_vector.hpp b/src/include/miopen/inline_vector.hpp index 2fccf69fe9..e8b123b032 100644 --- a/src/include/miopen/inline_vector.hpp +++ b/src/include/miopen/inline_vector.hpp @@ -221,16 +221,10 @@ class InlineVector storage[real_size++] = std::move(e); } - // Create element and add it to the back - template - void emplace_back(Args&&... args) - { - if(real_size == N) - { - MIOPEN_THROW("InlineVector already full"); - } - storage[real_size++] = T(std::forward(args)...); - } + /* + Because only scalar type is supported there is no need for emplace_back method. + Implement emplace_back method when adding support for other data types. + */ // Remove element from the back void pop_back() noexcept { real_size = (real_size > 1) ? (real_size - 1) : 0; }