1 // Licensed to the Apache Software Foundation (ASF) under one 2 // or more contributor license agreements. See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership. The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 #include "benchmark/benchmark.h" 19 20 #include "arrow/sparse_tensor.h" 21 #include "arrow/testing/gtest_util.h" 22 23 #include <random> 24 25 namespace arrow { 26 27 enum ContiguousType { ROW_MAJOR, COLUMN_MAJOR, STRIDED }; 28 29 template <ContiguousType contiguous_type, typename ValueType, typename IndexType> 30 class TensorConversionFixture : public benchmark::Fixture { 31 protected: 32 using c_value_type = typename ValueType::c_type; 33 using c_index_type = typename IndexType::c_type; 34 35 std::shared_ptr<DataType> value_type_ = TypeTraits<ValueType>::type_singleton(); 36 std::shared_ptr<DataType> index_type_ = TypeTraits<IndexType>::type_singleton(); 37 38 std::vector<c_value_type> values_; 39 std::shared_ptr<Tensor> tensor_; 40 41 public: SetUp(const::benchmark::State & state)42 void SetUp(const ::benchmark::State& state) { 43 std::vector<int64_t> shape = {30, 8, 20, 9}; 44 auto n = std::accumulate(shape.begin(), shape.end(), int64_t(1), 45 [](int64_t acc, int64_t i) { return acc * i; }); 46 auto m = n / 100; 47 48 switch (contiguous_type) { 49 case STRIDED: 50 values_.resize(2 * n); 51 for (int64_t i = 0; i < 100; ++i) { 52 values_[2 * i * m] = static_cast<c_value_type>(i); 53 } 54 break; 55 default: 56 values_.resize(n); 57 for (int64_t i = 0; i < 100; ++i) { 58 values_[i * m] = static_cast<c_value_type>(i); 59 } 60 break; 61 } 62 63 std::vector<int64_t> strides; 64 int64_t total = sizeof(c_value_type); 65 switch (contiguous_type) { 66 case ROW_MAJOR: 67 break; 68 case COLUMN_MAJOR: { 69 for (auto i : shape) { 70 strides.push_back(total); 71 total *= i; 72 } 73 break; 74 } 75 case STRIDED: { 76 total *= 2; 77 for (auto i : shape) { 78 strides.push_back(total); 79 total *= i; 80 } 81 break; 82 } 83 } 84 ABORT_NOT_OK( 85 Tensor::Make(value_type_, Buffer::Wrap(values_), shape, strides).Value(&tensor_)); 86 } 87 SetUpRowMajor()88 void SetUpRowMajor() {} 89 }; 90 91 template <ContiguousType contiguous_type, typename ValueType, typename IndexType> 92 class MatrixConversionFixture : public benchmark::Fixture { 93 protected: 94 using c_value_type = typename ValueType::c_type; 95 using c_index_type = typename IndexType::c_type; 96 97 std::shared_ptr<DataType> value_type_ = TypeTraits<ValueType>::type_singleton(); 98 std::shared_ptr<DataType> index_type_ = TypeTraits<IndexType>::type_singleton(); 99 100 std::vector<c_value_type> values_; 101 std::shared_ptr<Tensor> tensor_; 102 103 public: SetUp(const::benchmark::State & state)104 void SetUp(const ::benchmark::State& state) { 105 std::vector<int64_t> shape = {88, 113}; 106 auto n = std::accumulate(shape.begin(), shape.end(), int64_t(1), 107 [](int64_t acc, int64_t i) { return acc * i; }); 108 auto m = n / 100; 109 110 switch (contiguous_type) { 111 case STRIDED: 112 values_.resize(2 * n); 113 for (int64_t i = 0; i < 100; ++i) { 114 values_[2 * i * m] = static_cast<c_value_type>(i); 115 } 116 break; 117 default: 118 values_.resize(n); 119 for (int64_t i = 0; i < 100; ++i) { 120 values_[i * m] = static_cast<c_value_type>(i); 121 } 122 break; 123 } 124 125 std::vector<int64_t> strides; 126 int64_t total = sizeof(c_value_type); 127 switch (contiguous_type) { 128 case ROW_MAJOR: 129 break; 130 case COLUMN_MAJOR: { 131 for (auto i : shape) { 132 strides.push_back(total); 133 total *= i; 134 } 135 break; 136 } 137 case STRIDED: { 138 total *= 2; 139 for (auto i : shape) { 140 strides.push_back(total); 141 total *= i; 142 } 143 break; 144 } 145 } 146 ABORT_NOT_OK(Tensor::Make(value_type_, Buffer::Wrap(values_), shape).Value(&tensor_)); 147 } 148 }; 149 150 #define DEFINE_TYPED_TENSOR_CONVERSION_FIXTURE(value_type_name) \ 151 template <typename IndexType> \ 152 using value_type_name##RowMajorTensorConversionFixture = \ 153 TensorConversionFixture<ROW_MAJOR, value_type_name##Type, IndexType>; \ 154 template <typename IndexType> \ 155 using value_type_name##ColumnMajorTensorConversionFixture = \ 156 TensorConversionFixture<COLUMN_MAJOR, value_type_name##Type, IndexType>; \ 157 template <typename IndexType> \ 158 using value_type_name##StridedTensorConversionFixture = \ 159 TensorConversionFixture<STRIDED, value_type_name##Type, IndexType> 160 161 DEFINE_TYPED_TENSOR_CONVERSION_FIXTURE(Int8); 162 DEFINE_TYPED_TENSOR_CONVERSION_FIXTURE(Float); 163 DEFINE_TYPED_TENSOR_CONVERSION_FIXTURE(Double); 164 165 #define DEFINE_TYPED_MATRIX_CONVERSION_FIXTURE(value_type_name) \ 166 template <typename IndexType> \ 167 using value_type_name##RowMajorMatrixConversionFixture = \ 168 MatrixConversionFixture<ROW_MAJOR, value_type_name##Type, IndexType>; \ 169 template <typename IndexType> \ 170 using value_type_name##ColumnMajorMatrixConversionFixture = \ 171 MatrixConversionFixture<COLUMN_MAJOR, value_type_name##Type, IndexType>; \ 172 template <typename IndexType> \ 173 using value_type_name##StridedMatrixConversionFixture = \ 174 MatrixConversionFixture<STRIDED, value_type_name##Type, IndexType> 175 176 DEFINE_TYPED_MATRIX_CONVERSION_FIXTURE(Int8); 177 DEFINE_TYPED_MATRIX_CONVERSION_FIXTURE(Float); 178 DEFINE_TYPED_MATRIX_CONVERSION_FIXTURE(Double); 179 180 #define BENCHMARK_CONVERT_TENSOR_(Contiguous, kind, format, value_type_name, \ 181 index_type_name) \ 182 BENCHMARK_TEMPLATE_F(value_type_name##Contiguous##kind##ConversionFixture, \ 183 ConvertToSparse##format##kind##index_type_name, \ 184 index_type_name##Type) \ 185 (benchmark::State & state) { /* NOLINT non-const reference */ \ 186 std::shared_ptr<Sparse##format##kind> sparse_tensor; \ 187 for (auto _ : state) { \ 188 ABORT_NOT_OK(Sparse##format##kind::Make(*this->tensor_, this->index_type_) \ 189 .Value(&sparse_tensor)); \ 190 } \ 191 benchmark::DoNotOptimize(sparse_tensor); \ 192 state.SetItemsProcessed(state.iterations() * this->tensor_->size()); \ 193 state.SetBytesProcessed(state.iterations() * this->tensor_->data()->size()); \ 194 } 195 196 #define BENCHMARK_CONVERT_TENSOR(kind, format, value_type_name, index_type_name) \ 197 BENCHMARK_CONVERT_TENSOR_(RowMajor, kind, format, value_type_name, index_type_name); \ 198 BENCHMARK_CONVERT_TENSOR_(ColumnMajor, kind, format, value_type_name, \ 199 index_type_name); \ 200 BENCHMARK_CONVERT_TENSOR_(Strided, kind, format, value_type_name, index_type_name) 201 202 BENCHMARK_CONVERT_TENSOR(Tensor, COO, Int8, Int32); 203 BENCHMARK_CONVERT_TENSOR(Tensor, COO, Int8, Int64); 204 BENCHMARK_CONVERT_TENSOR(Tensor, COO, Float, Int32); 205 BENCHMARK_CONVERT_TENSOR(Tensor, COO, Float, Int64); 206 BENCHMARK_CONVERT_TENSOR(Tensor, COO, Double, Int32); 207 BENCHMARK_CONVERT_TENSOR(Tensor, COO, Double, Int64); 208 209 BENCHMARK_CONVERT_TENSOR(Matrix, CSR, Int8, Int8); 210 BENCHMARK_CONVERT_TENSOR(Matrix, CSR, Int8, Int16); 211 BENCHMARK_CONVERT_TENSOR(Matrix, CSR, Float, Int32); 212 BENCHMARK_CONVERT_TENSOR(Matrix, CSR, Float, Int64); 213 BENCHMARK_CONVERT_TENSOR(Matrix, CSR, Double, Int32); 214 BENCHMARK_CONVERT_TENSOR(Matrix, CSR, Double, Int64); 215 216 BENCHMARK_CONVERT_TENSOR(Matrix, CSC, Int8, Int32); 217 BENCHMARK_CONVERT_TENSOR(Matrix, CSC, Int8, Int64); 218 BENCHMARK_CONVERT_TENSOR(Matrix, CSC, Float, Int32); 219 BENCHMARK_CONVERT_TENSOR(Matrix, CSC, Float, Int64); 220 BENCHMARK_CONVERT_TENSOR(Matrix, CSC, Double, Int32); 221 BENCHMARK_CONVERT_TENSOR(Matrix, CSC, Double, Int64); 222 223 BENCHMARK_CONVERT_TENSOR(Tensor, CSF, Int8, Int32); 224 BENCHMARK_CONVERT_TENSOR(Tensor, CSF, Int8, Int64); 225 BENCHMARK_CONVERT_TENSOR(Tensor, CSF, Float, Int32); 226 BENCHMARK_CONVERT_TENSOR(Tensor, CSF, Float, Int64); 227 BENCHMARK_CONVERT_TENSOR(Tensor, CSF, Double, Int32); 228 BENCHMARK_CONVERT_TENSOR(Tensor, CSF, Double, Int64); 229 230 } // namespace arrow 231