* Add feature score support for linear model. * Port R interface to the new implementation. * Add linear model support in Python. Co-authored-by: Philip Hyunsu Cho <chohyu01@cs.washington.edu>
114 lines
3.5 KiB
C++
114 lines
3.5 KiB
C++
/*!
|
|
* Copyright 2021 by Contributors
|
|
* \file linalg.h
|
|
* \brief Linear algebra related utilities.
|
|
*/
|
|
#ifndef XGBOOST_LINALG_H_
|
|
#define XGBOOST_LINALG_H_
|
|
|
|
#include <xgboost/span.h>
|
|
#include <xgboost/host_device_vector.h>
|
|
#include <xgboost/generic_parameters.h>
|
|
|
|
#include <array>
|
|
#include <algorithm>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace xgboost {
|
|
/*!
|
|
* \brief A view over a matrix on contiguous storage.
|
|
*
|
|
* \tparam T data type of matrix
|
|
*/
|
|
template <typename T> class MatrixView {
|
|
int32_t device_;
|
|
common::Span<T> values_;
|
|
size_t strides_[2];
|
|
size_t shape_[2];
|
|
|
|
template <typename Vec> static auto InferValues(Vec *vec, int32_t device) {
|
|
return device == GenericParameter::kCpuId ? vec->HostSpan()
|
|
: vec->DeviceSpan();
|
|
}
|
|
|
|
public:
|
|
/*!
|
|
* \param vec storage.
|
|
* \param strides Strides for matrix.
|
|
* \param shape Rows and columns.
|
|
* \param device Where the data is stored in.
|
|
*/
|
|
MatrixView(HostDeviceVector<T> *vec, std::array<size_t, 2> strides,
|
|
std::array<size_t, 2> shape, int32_t device)
|
|
: device_{device}, values_{InferValues(vec, device)} {
|
|
std::copy(strides.cbegin(), strides.cend(), strides_);
|
|
std::copy(shape.cbegin(), shape.cend(), shape_);
|
|
}
|
|
MatrixView(HostDeviceVector<std::remove_const_t<T>> const *vec,
|
|
std::array<size_t, 2> strides, std::array<size_t, 2> shape,
|
|
int32_t device)
|
|
: device_{device}, values_{InferValues(vec, device)} {
|
|
std::copy(strides.cbegin(), strides.cend(), strides_);
|
|
std::copy(shape.cbegin(), shape.cend(), shape_);
|
|
}
|
|
/*! \brief Row major constructor. */
|
|
MatrixView(HostDeviceVector<T> *vec, std::array<size_t, 2> shape,
|
|
int32_t device)
|
|
: device_{device}, values_{InferValues(vec, device)} {
|
|
std::copy(shape.cbegin(), shape.cend(), shape_);
|
|
strides_[0] = shape[1];
|
|
strides_[1] = 1;
|
|
}
|
|
MatrixView(std::vector<T> *vec, std::array<size_t, 2> shape)
|
|
: device_{GenericParameter::kCpuId}, values_{*vec} {
|
|
CHECK_EQ(vec->size(), shape[0] * shape[1]);
|
|
std::copy(shape.cbegin(), shape.cend(), shape_);
|
|
strides_[0] = shape[1];
|
|
strides_[1] = 1;
|
|
}
|
|
MatrixView(HostDeviceVector<std::remove_const_t<T>> const *vec,
|
|
std::array<size_t, 2> shape, int32_t device)
|
|
: device_{device}, values_{InferValues(vec, device)} {
|
|
std::copy(shape.cbegin(), shape.cend(), shape_);
|
|
strides_[0] = shape[1];
|
|
strides_[1] = 1;
|
|
}
|
|
|
|
XGBOOST_DEVICE T const &operator()(size_t r, size_t c) const {
|
|
return values_[strides_[0] * r + strides_[1] * c];
|
|
}
|
|
XGBOOST_DEVICE T &operator()(size_t r, size_t c) {
|
|
return values_[strides_[0] * r + strides_[1] * c];
|
|
}
|
|
|
|
auto Strides() const { return strides_; }
|
|
auto Shape() const { return shape_; }
|
|
auto Values() const { return values_; }
|
|
auto Size() const { return shape_[0] * shape_[1]; }
|
|
auto DeviceIdx() const { return device_; }
|
|
};
|
|
|
|
/*! \brief A slice for 1 column of MatrixView. Can be extended to row if needed. */
|
|
template <typename T> class VectorView {
|
|
MatrixView<T> matrix_;
|
|
size_t column_;
|
|
|
|
public:
|
|
explicit VectorView(MatrixView<T> matrix, size_t column)
|
|
: matrix_{std::move(matrix)}, column_{column} {}
|
|
|
|
XGBOOST_DEVICE T &operator[](size_t i) {
|
|
return matrix_(i, column_);
|
|
}
|
|
|
|
XGBOOST_DEVICE T const &operator[](size_t i) const {
|
|
return matrix_(i, column_);
|
|
}
|
|
|
|
size_t Size() { return matrix_.Shape()[0]; }
|
|
int32_t DeviceIdx() const { return matrix_.DeviceIdx(); }
|
|
};
|
|
} // namespace xgboost
|
|
#endif // XGBOOST_LINALG_H_
|