diff --git a/include/xgboost/linalg.h b/include/xgboost/linalg.h index e4449bb8986b..b4fea37de09e 100644 --- a/include/xgboost/linalg.h +++ b/include/xgboost/linalg.h @@ -6,10 +6,12 @@ #ifndef XGBOOST_LINALG_H_ #define XGBOOST_LINALG_H_ +#include #include #include #include +#include #include #include #include @@ -24,8 +26,7 @@ constexpr size_t Offset(S (&strides)[D], size_t n, size_t dim, Head head) { } template -constexpr size_t Offset(S (&strides)[D], size_t n, size_t dim, Head head, - Tail &&...rest) { +constexpr size_t Offset(S (&strides)[D], size_t n, size_t dim, Head head, Tail &&...rest) { assert(dim < D); return Offset(strides, n + (head * strides[dim]), dim + 1, rest...); } @@ -36,7 +37,8 @@ struct IntTag {}; /** * \brief Calculate the dimension of sliced tensor. */ -template constexpr int32_t CalcSliceDim() { +template +constexpr int32_t CalcSliceDim() { return std::is_same::value ? 0 : 1; } @@ -49,8 +51,7 @@ template using RemoveCRType = std::remove_const_t>; template -using IndexToTag = std::conditional_t>::value, - IntTag, AllTag>; +using IndexToTag = std::conditional_t>::value, IntTag, AllTag>; template constexpr XGBOOST_DEVICE auto UnrollLoop(Fn fn) { @@ -74,7 +75,8 @@ constexpr detail::AllTag All() { return {}; } * \brief A tensor view with static type and shape, it implements indexing and * slicing. */ -template class TensorView { +template +class TensorView { using ShapeT = size_t[kDim]; using StrideT = ShapeT; @@ -102,40 +104,34 @@ template class TensorView { }; template - XGBOOST_DEVICE SliceHelper MakeSliceDim(size_t old_dim, size_t new_dim, - size_t new_shape[D], - size_t new_stride[D], - detail::AllTag) const { + XGBOOST_DEVICE SliceHelper MakeSliceDim(size_t old_dim, size_t new_dim, size_t new_shape[D], + size_t new_stride[D], detail::AllTag) const { new_stride[new_dim] = stride_[old_dim]; new_shape[new_dim] = shape_[old_dim]; return {old_dim + 1, new_dim + 1, 0}; } template - XGBOOST_DEVICE SliceHelper MakeSliceDim(size_t old_dim, size_t new_dim, - size_t new_shape[D], + XGBOOST_DEVICE SliceHelper MakeSliceDim(size_t old_dim, size_t new_dim, size_t new_shape[D], size_t new_stride[D], detail::AllTag, S &&...slices) const { new_stride[new_dim] = stride_[old_dim]; new_shape[new_dim] = shape_[old_dim]; - return MakeSliceDim(old_dim + 1, new_dim + 1, new_shape, new_stride, - slices...); + return MakeSliceDim(old_dim + 1, new_dim + 1, new_shape, new_stride, slices...); } template - XGBOOST_DEVICE SliceHelper MakeSliceDim(size_t old_dim, size_t new_dim, - size_t new_shape[D], + XGBOOST_DEVICE SliceHelper MakeSliceDim(size_t old_dim, size_t new_dim, size_t new_shape[D], size_t new_stride[D], Index i) const { return {old_dim + 1, new_dim, stride_[old_dim] * i}; } template - XGBOOST_DEVICE std::enable_if_t::value, SliceHelper> - MakeSliceDim(size_t old_dim, size_t new_dim, size_t new_shape[D], - size_t new_stride[D], Index i, S &&...slices) const { + XGBOOST_DEVICE std::enable_if_t::value, SliceHelper> MakeSliceDim( + size_t old_dim, size_t new_dim, size_t new_shape[D], size_t new_stride[D], Index i, + S &&...slices) const { auto offset = stride_[old_dim] * i; - auto res = - MakeSliceDim(old_dim + 1, new_dim, new_shape, new_stride, slices...); + auto res = MakeSliceDim(old_dim + 1, new_dim, new_shape, new_stride, slices...); return {res.old_dim, res.new_dim, res.offset + offset}; } @@ -148,8 +144,7 @@ template class TensorView { * \brief Create a tensor with data and shape. */ template - XGBOOST_DEVICE TensorView(common::Span data, I const (&shape)[D], - int32_t device) + XGBOOST_DEVICE TensorView(common::Span data, I const (&shape)[D], int32_t device) : data_{data}, device_{device} { static_assert(D > 0 && D <= kDim, "Invalid shape."); // shape @@ -170,8 +165,8 @@ template class TensorView { * stride can be calculated from shape. */ template - XGBOOST_DEVICE TensorView(common::Span data, I const (&shape)[D], - I const (&stride)[D], int32_t device) + XGBOOST_DEVICE TensorView(common::Span data, I const (&shape)[D], I const (&stride)[D], + int32_t device) : data_{data}, device_{device} { static_assert(D == kDim, "Invalid shape & stride."); detail::UnrollLoop([&](auto i) { @@ -202,7 +197,8 @@ template class TensorView { * * \endcode */ - template XGBOOST_DEVICE T &operator()(Index &&...index) { + template + XGBOOST_DEVICE T &operator()(Index &&...index) { static_assert(sizeof...(index) <= kDim, "Invalid index."); size_t offset = detail::Offset(stride_, 0ul, 0ul, index...); return data_[offset]; @@ -229,29 +225,27 @@ template class TensorView { * * \endcode */ - template XGBOOST_DEVICE auto Slice(S &&...slices) const { + template + XGBOOST_DEVICE auto Slice(S &&...slices) const { static_assert(sizeof...(slices) <= kDim, "Invalid slice."); int32_t constexpr kNewDim{detail::CalcSliceDim...>()}; size_t new_shape[kNewDim]; size_t new_stride[kNewDim]; - auto res = MakeSliceDim(size_t(0), size_t(0), new_shape, - new_stride, slices...); + auto res = MakeSliceDim(size_t(0), size_t(0), new_shape, new_stride, slices...); // ret is a different type due to changed dimension, so we can not access its private // fields. - TensorView ret{data_.subspan(data_.empty() ? 0 : res.offset), - new_shape, new_stride, device_}; + TensorView ret{data_.subspan(data_.empty() ? 0 : res.offset), new_shape, new_stride, + device_}; return ret; } - XGBOOST_DEVICE auto Shape() const { - return common::Span{shape_}; - } + XGBOOST_DEVICE auto Shape() const { return common::Span{shape_}; } XGBOOST_DEVICE auto Shape(size_t i) const { return shape_[i]; } - XGBOOST_DEVICE auto cbegin() const { return data_.cbegin(); } // NOLINT - XGBOOST_DEVICE auto cend() const { return data_.cend(); } // NOLINT - XGBOOST_DEVICE auto begin() { return data_.begin(); } // NOLINT - XGBOOST_DEVICE auto end() { return data_.end(); } // NOLINT + XGBOOST_DEVICE auto cbegin() const { return data_.cbegin(); } // NOLINT + XGBOOST_DEVICE auto cend() const { return data_.cend(); } // NOLINT + XGBOOST_DEVICE auto begin() { return data_.begin(); } // NOLINT + XGBOOST_DEVICE auto end() { return data_.end(); } // NOLINT XGBOOST_DEVICE size_t Size() const { return size_; } XGBOOST_DEVICE auto Values() const { return data_; } @@ -273,6 +267,6 @@ using VectorView = TensorView; */ template using MatrixView = TensorView; -} // namespace linalg -} // namespace xgboost +} // namespace linalg +} // namespace xgboost #endif // XGBOOST_LINALG_H_ diff --git a/tests/cpp/common/test_linalg.cc b/tests/cpp/common/test_linalg.cc index 1d3e149c9a6a..13abb63f5659 100644 --- a/tests/cpp/common/test_linalg.cc +++ b/tests/cpp/common/test_linalg.cc @@ -1,19 +1,18 @@ #include -#include #include #include +#include + namespace xgboost { namespace linalg { -auto MakeMatrixFromTest(HostDeviceVector *storage, size_t n_rows, - size_t n_cols) { +auto MakeMatrixFromTest(HostDeviceVector *storage, size_t n_rows, size_t n_cols) { storage->Resize(n_rows * n_cols); auto &h_storage = storage->HostVector(); std::iota(h_storage.begin(), h_storage.end(), 0); - auto m = linalg::TensorView{ - h_storage, {n_rows, static_cast(n_cols)}, -1}; + auto m = linalg::TensorView{h_storage, {n_rows, static_cast(n_cols)}, -1}; return m; } @@ -57,10 +56,7 @@ TEST(Linalg, Tensor) { ASSERT_EQ(s.Shape()[1], 4); std::vector> sol{ - {12.0, 13.0, 14.0, 15.0}, - {16.0, 17.0, 18.0, 19.0}, - {20.0, 21.0, 22.0, 23.0} - }; + {12.0, 13.0, 14.0, 15.0}, {16.0, 17.0, 18.0, 19.0}, {20.0, 21.0, 22.0, 23.0}}; for (size_t i = 0; i < s.Shape()[0]; ++i) { for (size_t j = 0; j < s.Shape()[1]; ++j) { ASSERT_EQ(s(i, j), sol[i][j]); @@ -113,5 +109,5 @@ TEST(Linalg, Empty) { ASSERT_EQ(s.Shape(0), 0); } } -} // namespace linalg -} // namespace xgboost +} // namespace linalg +} // namespace xgboost