Replaced std::vector-based interfaces with HostDeviceVector-based interfaces. (#3116)
* Replaced std::vector-based interfaces with HostDeviceVector-based interfaces. - replacement was performed in the learner, boosters, predictors, updaters, and objective functions - only interfaces used in training were replaced; interfaces like PredictInstance() still use std::vector - refactoring necessary for replacement of interfaces was also performed, such as using HostDeviceVector in prediction cache * HostDeviceVector-based interfaces for custom objective function example plugin.
This commit is contained in:
committed by
Rory Mitchell
parent
11bfa8584d
commit
d5992dd881
@@ -12,13 +12,27 @@ namespace xgboost {
|
||||
|
||||
template <typename T>
|
||||
struct HostDeviceVectorImpl {
|
||||
explicit HostDeviceVectorImpl(size_t size) : data_h_(size) {}
|
||||
explicit HostDeviceVectorImpl(size_t size, T v) : data_h_(size, v) {}
|
||||
explicit HostDeviceVectorImpl(std::initializer_list<T> init) : data_h_(init) {}
|
||||
explicit HostDeviceVectorImpl(const std::vector<T>& init) : data_h_(init) {}
|
||||
std::vector<T> data_h_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
HostDeviceVector<T>::HostDeviceVector(size_t size, int device) : impl_(nullptr) {
|
||||
impl_ = new HostDeviceVectorImpl<T>(size);
|
||||
HostDeviceVector<T>::HostDeviceVector(size_t size, T v, int device) : impl_(nullptr) {
|
||||
impl_ = new HostDeviceVectorImpl<T>(size, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HostDeviceVector<T>::HostDeviceVector(std::initializer_list<T> init, int device)
|
||||
: impl_(nullptr) {
|
||||
impl_ = new HostDeviceVectorImpl<T>(init);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HostDeviceVector<T>::HostDeviceVector(const std::vector<T>& init, int device)
|
||||
: impl_(nullptr) {
|
||||
impl_ = new HostDeviceVectorImpl<T>(init);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -41,8 +55,8 @@ template <typename T>
|
||||
std::vector<T>& HostDeviceVector<T>::data_h() { return impl_->data_h_; }
|
||||
|
||||
template <typename T>
|
||||
void HostDeviceVector<T>::resize(size_t new_size, int new_device) {
|
||||
impl_->data_h_.resize(new_size);
|
||||
void HostDeviceVector<T>::resize(size_t new_size, T v, int new_device) {
|
||||
impl_->data_h_.resize(new_size, v);
|
||||
}
|
||||
|
||||
// explicit instantiations are required, as HostDeviceVector isn't header-only
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*!
|
||||
* Copyright 2017 XGBoost contributors
|
||||
*/
|
||||
|
||||
#include "./host_device_vector.h"
|
||||
#include "./device_helpers.cuh"
|
||||
|
||||
@@ -8,13 +9,25 @@ namespace xgboost {
|
||||
|
||||
template <typename T>
|
||||
struct HostDeviceVectorImpl {
|
||||
HostDeviceVectorImpl(size_t size, int device)
|
||||
HostDeviceVectorImpl(size_t size, T v, int device)
|
||||
: device_(device), on_d_(device >= 0) {
|
||||
if (on_d_) {
|
||||
dh::safe_cuda(cudaSetDevice(device_));
|
||||
data_d_.resize(size);
|
||||
data_d_.resize(size, v);
|
||||
} else {
|
||||
data_h_.resize(size);
|
||||
data_h_.resize(size, v);
|
||||
}
|
||||
}
|
||||
// Init can be std::vector<T> or std::initializer_list<T>
|
||||
template <class Init>
|
||||
HostDeviceVectorImpl(const Init& init, int device)
|
||||
: device_(device), on_d_(device >= 0) {
|
||||
if (on_d_) {
|
||||
dh::safe_cuda(cudaSetDevice(device_));
|
||||
data_d_.resize(init.size());
|
||||
thrust::copy(init.begin(), init.end(), data_d_.begin());
|
||||
} else {
|
||||
data_h_ = init;
|
||||
}
|
||||
}
|
||||
HostDeviceVectorImpl(const HostDeviceVectorImpl<T>&) = delete;
|
||||
@@ -41,17 +54,18 @@ struct HostDeviceVectorImpl {
|
||||
lazy_sync_host();
|
||||
return data_h_;
|
||||
}
|
||||
void resize(size_t new_size, int new_device) {
|
||||
void resize(size_t new_size, T v, int new_device) {
|
||||
if (new_size == this->size() && new_device == device_)
|
||||
return;
|
||||
device_ = new_device;
|
||||
if (new_device != -1)
|
||||
device_ = new_device;
|
||||
// if !on_d_, but the data size is 0 and the device is set,
|
||||
// resize the data on device instead
|
||||
if (!on_d_ && (data_h_.size() > 0 || device_ == -1)) {
|
||||
data_h_.resize(new_size);
|
||||
data_h_.resize(new_size, v);
|
||||
} else {
|
||||
dh::safe_cuda(cudaSetDevice(device_));
|
||||
data_d_.resize(new_size);
|
||||
data_d_.resize(new_size, v);
|
||||
on_d_ = true;
|
||||
}
|
||||
}
|
||||
@@ -90,8 +104,20 @@ struct HostDeviceVectorImpl {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
HostDeviceVector<T>::HostDeviceVector(size_t size, int device) : impl_(nullptr) {
|
||||
impl_ = new HostDeviceVectorImpl<T>(size, device);
|
||||
HostDeviceVector<T>::HostDeviceVector(size_t size, T v, int device) : impl_(nullptr) {
|
||||
impl_ = new HostDeviceVectorImpl<T>(size, v, device);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HostDeviceVector<T>::HostDeviceVector(std::initializer_list<T> init, int device)
|
||||
: impl_(nullptr) {
|
||||
impl_ = new HostDeviceVectorImpl<T>(init, device);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HostDeviceVector<T>::HostDeviceVector(const std::vector<T>& init, int device)
|
||||
: impl_(nullptr) {
|
||||
impl_ = new HostDeviceVectorImpl<T>(init, device);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -124,8 +150,8 @@ template <typename T>
|
||||
std::vector<T>& HostDeviceVector<T>::data_h() { return impl_->data_h(); }
|
||||
|
||||
template <typename T>
|
||||
void HostDeviceVector<T>::resize(size_t new_size, int new_device) {
|
||||
impl_->resize(new_size, new_device);
|
||||
void HostDeviceVector<T>::resize(size_t new_size, T v, int new_device) {
|
||||
impl_->resize(new_size, v, new_device);
|
||||
}
|
||||
|
||||
// explicit instantiations are required, as HostDeviceVector isn't header-only
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#define XGBOOST_COMMON_HOST_DEVICE_VECTOR_H_
|
||||
|
||||
#include <cstdlib>
|
||||
#include <initializer_list>
|
||||
#include <vector>
|
||||
|
||||
// only include thrust-related files if host_device_vector.h
|
||||
@@ -61,7 +62,9 @@ template <typename T> struct HostDeviceVectorImpl;
|
||||
template <typename T>
|
||||
class HostDeviceVector {
|
||||
public:
|
||||
explicit HostDeviceVector(size_t size = 0, int device = -1);
|
||||
explicit HostDeviceVector(size_t size = 0, T v = T(), int device = -1);
|
||||
HostDeviceVector(std::initializer_list<T> init, int device = -1);
|
||||
explicit HostDeviceVector(const std::vector<T>& init, int device = -1);
|
||||
~HostDeviceVector();
|
||||
HostDeviceVector(const HostDeviceVector<T>&) = delete;
|
||||
HostDeviceVector(HostDeviceVector<T>&&) = delete;
|
||||
@@ -70,6 +73,7 @@ class HostDeviceVector {
|
||||
size_t size() const;
|
||||
int device() const;
|
||||
T* ptr_d(int device);
|
||||
T* ptr_h() { return data_h().data(); }
|
||||
|
||||
// only define functions returning device_ptr
|
||||
// if HostDeviceVector.h is included from a .cu file
|
||||
@@ -79,17 +83,9 @@ class HostDeviceVector {
|
||||
#endif
|
||||
|
||||
std::vector<T>& data_h();
|
||||
void resize(size_t new_size, int new_device);
|
||||
|
||||
// helper functions in case a function needs to be templated
|
||||
// to work for both HostDeviceVector and std::vector
|
||||
static std::vector<T>& data_h(HostDeviceVector<T>* v) {
|
||||
return v->data_h();
|
||||
}
|
||||
|
||||
static std::vector<T>& data_h(std::vector<T>* v) {
|
||||
return *v;
|
||||
}
|
||||
// passing in new_device == -1 keeps the device as is
|
||||
void resize(size_t new_size, T v = T(), int new_device = -1);
|
||||
|
||||
private:
|
||||
HostDeviceVectorImpl<T>* impl_;
|
||||
|
||||
Reference in New Issue
Block a user