Lazy initialization of device vector. (#5173)
* Lazy initialization of device vector. * Fix #5162. * Disable copy constructor of HostDeviceVector. Prevents implicit copying. * Fix CPU build. * Bring back move assignment operator.
This commit is contained in:
parent
77cfbff5a7
commit
ee287808fb
@ -59,8 +59,25 @@ class MetaInfo {
|
|||||||
* can be used to specify initial prediction to boost from.
|
* can be used to specify initial prediction to boost from.
|
||||||
*/
|
*/
|
||||||
HostDeviceVector<bst_float> base_margin_;
|
HostDeviceVector<bst_float> base_margin_;
|
||||||
|
|
||||||
/*! \brief default constructor */
|
/*! \brief default constructor */
|
||||||
MetaInfo() = default;
|
MetaInfo() = default;
|
||||||
|
MetaInfo& operator=(MetaInfo const& that) {
|
||||||
|
this->num_row_ = that.num_row_;
|
||||||
|
this->num_col_ = that.num_col_;
|
||||||
|
this->num_nonzero_ = that.num_nonzero_;
|
||||||
|
|
||||||
|
this->labels_.Resize(that.labels_.Size());
|
||||||
|
this->labels_.Copy(that.labels_);
|
||||||
|
|
||||||
|
this->group_ptr_ = that.group_ptr_;
|
||||||
|
|
||||||
|
this->weights_.Resize(that.weights_.Size());
|
||||||
|
this->weights_.Copy(that.weights_);
|
||||||
|
this->base_margin_.Resize(that.base_margin_.Size());
|
||||||
|
this->base_margin_.Copy(that.base_margin_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
/*!
|
/*!
|
||||||
* \brief Get weight of each instances.
|
* \brief Get weight of each instances.
|
||||||
* \param i Instance index.
|
* \param i Instance index.
|
||||||
|
|||||||
@ -88,8 +88,13 @@ class HostDeviceVector {
|
|||||||
HostDeviceVector(std::initializer_list<T> init, int device = -1);
|
HostDeviceVector(std::initializer_list<T> init, int device = -1);
|
||||||
explicit HostDeviceVector(const std::vector<T>& init, int device = -1);
|
explicit HostDeviceVector(const std::vector<T>& init, int device = -1);
|
||||||
~HostDeviceVector();
|
~HostDeviceVector();
|
||||||
HostDeviceVector(const HostDeviceVector<T>&);
|
|
||||||
HostDeviceVector<T>& operator=(const HostDeviceVector<T>&);
|
HostDeviceVector(const HostDeviceVector<T>&) = delete;
|
||||||
|
HostDeviceVector(HostDeviceVector<T>&&);
|
||||||
|
|
||||||
|
HostDeviceVector<T>& operator=(const HostDeviceVector<T>&) = delete;
|
||||||
|
HostDeviceVector<T>& operator=(HostDeviceVector<T>&&);
|
||||||
|
|
||||||
size_t Size() const;
|
size_t Size() const;
|
||||||
int DeviceIdx() const;
|
int DeviceIdx() const;
|
||||||
common::Span<T> DeviceSpan();
|
common::Span<T> DeviceSpan();
|
||||||
@ -116,6 +121,7 @@ class HostDeviceVector {
|
|||||||
bool HostCanWrite() const;
|
bool HostCanWrite() const;
|
||||||
bool DeviceCanRead() const;
|
bool DeviceCanRead() const;
|
||||||
bool DeviceCanWrite() const;
|
bool DeviceCanWrite() const;
|
||||||
|
GPUAccess DeviceAccess() const;
|
||||||
|
|
||||||
void SetDevice(int device) const;
|
void SetDevice(int device) const;
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include <xgboost/base.h>
|
#include <xgboost/base.h>
|
||||||
#include <xgboost/data.h>
|
#include <xgboost/data.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "xgboost/host_device_vector.h"
|
#include "xgboost/host_device_vector.h"
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ struct HostDeviceVectorImpl {
|
|||||||
explicit HostDeviceVectorImpl(size_t size, T v) : data_h_(size, v) {}
|
explicit HostDeviceVectorImpl(size_t size, T v) : data_h_(size, v) {}
|
||||||
HostDeviceVectorImpl(std::initializer_list<T> init) : data_h_(init) {}
|
HostDeviceVectorImpl(std::initializer_list<T> init) : data_h_(init) {}
|
||||||
explicit HostDeviceVectorImpl(std::vector<T> init) : data_h_(std::move(init)) {}
|
explicit HostDeviceVectorImpl(std::vector<T> init) : data_h_(std::move(init)) {}
|
||||||
|
HostDeviceVectorImpl(HostDeviceVectorImpl&& that) : data_h_(std::move(that.data_h_)) {}
|
||||||
|
|
||||||
void Swap(HostDeviceVectorImpl &other) {
|
void Swap(HostDeviceVectorImpl &other) {
|
||||||
data_h_.swap(other.data_h_);
|
data_h_.swap(other.data_h_);
|
||||||
@ -47,6 +49,22 @@ HostDeviceVector<T>::HostDeviceVector(const std::vector<T>& init, int device)
|
|||||||
impl_ = new HostDeviceVectorImpl<T>(init);
|
impl_ = new HostDeviceVectorImpl<T>(init);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
HostDeviceVector<T>::HostDeviceVector(HostDeviceVector<T>&& that) {
|
||||||
|
impl_ = new HostDeviceVectorImpl<T>(std::move(*that.impl_));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
HostDeviceVector<T>& HostDeviceVector<T>::operator=(HostDeviceVector<T>&& that) {
|
||||||
|
if (this == &that) { return *this; }
|
||||||
|
|
||||||
|
std::unique_ptr<HostDeviceVectorImpl<T>> new_impl(
|
||||||
|
new HostDeviceVectorImpl<T>(std::move(*that.impl_)));
|
||||||
|
delete impl_;
|
||||||
|
impl_ = new_impl.release();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
HostDeviceVector<T>::~HostDeviceVector() {
|
HostDeviceVector<T>::~HostDeviceVector() {
|
||||||
delete impl_;
|
delete impl_;
|
||||||
@ -54,21 +72,8 @@ HostDeviceVector<T>::~HostDeviceVector() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
HostDeviceVector<T>::HostDeviceVector(const HostDeviceVector<T>& other)
|
GPUAccess HostDeviceVector<T>::DeviceAccess() const {
|
||||||
: impl_(nullptr) {
|
return kNone;
|
||||||
impl_ = new HostDeviceVectorImpl<T>(*other.impl_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
HostDeviceVector<T>& HostDeviceVector<T>::operator=(const HostDeviceVector<T>& other) {
|
|
||||||
if (this == &other) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
HostDeviceVectorImpl<T> newInstance(*other.impl_);
|
|
||||||
newInstance.Swap(*impl_);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class HostDeviceVectorImpl {
|
|||||||
if (device >= 0) {
|
if (device >= 0) {
|
||||||
gpu_access_ = GPUAccess::kWrite;
|
gpu_access_ = GPUAccess::kWrite;
|
||||||
SetDevice();
|
SetDevice();
|
||||||
data_d_.resize(size, v);
|
data_d_->resize(size, v);
|
||||||
} else {
|
} else {
|
||||||
data_h_.resize(size, v);
|
data_h_.resize(size, v);
|
||||||
}
|
}
|
||||||
@ -47,34 +47,40 @@ class HostDeviceVectorImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HostDeviceVectorImpl(HostDeviceVectorImpl<T>&& that) :
|
||||||
|
device_{that.device_},
|
||||||
|
data_h_{std::move(that.data_h_)},
|
||||||
|
data_d_{std::move(that.data_d_)},
|
||||||
|
gpu_access_{that.gpu_access_} {}
|
||||||
|
|
||||||
~HostDeviceVectorImpl() {
|
~HostDeviceVectorImpl() {
|
||||||
if (device_ >= 0) {
|
if (device_ >= 0) {
|
||||||
SetDevice();
|
SetDevice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Size() const { return HostCanRead() ? data_h_.size() : data_d_.size(); }
|
size_t Size() const { return HostCanRead() ? data_h_.size() : data_d_->size(); }
|
||||||
|
|
||||||
int DeviceIdx() const { return device_; }
|
int DeviceIdx() const { return device_; }
|
||||||
|
|
||||||
T* DevicePointer() {
|
T* DevicePointer() {
|
||||||
LazySyncDevice(GPUAccess::kWrite);
|
LazySyncDevice(GPUAccess::kWrite);
|
||||||
return data_d_.data().get();
|
return data_d_->data().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* ConstDevicePointer() {
|
const T* ConstDevicePointer() {
|
||||||
LazySyncDevice(GPUAccess::kRead);
|
LazySyncDevice(GPUAccess::kRead);
|
||||||
return data_d_.data().get();
|
return data_d_->data().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
common::Span<T> DeviceSpan() {
|
common::Span<T> DeviceSpan() {
|
||||||
LazySyncDevice(GPUAccess::kWrite);
|
LazySyncDevice(GPUAccess::kWrite);
|
||||||
return {data_d_.data().get(), Size()};
|
return {data_d_->data().get(), Size()};
|
||||||
}
|
}
|
||||||
|
|
||||||
common::Span<const T> ConstDeviceSpan() {
|
common::Span<const T> ConstDeviceSpan() {
|
||||||
LazySyncDevice(GPUAccess::kRead);
|
LazySyncDevice(GPUAccess::kRead);
|
||||||
return {data_d_.data().get(), Size()};
|
return {data_d_->data().get(), Size()};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fill(T v) { // NOLINT
|
void Fill(T v) { // NOLINT
|
||||||
@ -83,17 +89,19 @@ class HostDeviceVectorImpl {
|
|||||||
} else {
|
} else {
|
||||||
gpu_access_ = GPUAccess::kWrite;
|
gpu_access_ = GPUAccess::kWrite;
|
||||||
SetDevice();
|
SetDevice();
|
||||||
thrust::fill(data_d_.begin(), data_d_.end(), v);
|
thrust::fill(data_d_->begin(), data_d_->end(), v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Copy(HostDeviceVectorImpl<T>* other) {
|
void Copy(HostDeviceVectorImpl<T>* other) {
|
||||||
CHECK_EQ(Size(), other->Size());
|
CHECK_EQ(Size(), other->Size());
|
||||||
|
SetDevice(other->device_);
|
||||||
// Data is on host.
|
// Data is on host.
|
||||||
if (HostCanWrite() && other->HostCanWrite()) {
|
if (HostCanWrite() && other->HostCanWrite()) {
|
||||||
std::copy(other->data_h_.begin(), other->data_h_.end(), data_h_.begin());
|
std::copy(other->data_h_.begin(), other->data_h_.end(), data_h_.begin());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SetDevice();
|
||||||
CopyToDevice(other);
|
CopyToDevice(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,11 +146,11 @@ class HostDeviceVectorImpl {
|
|||||||
|
|
||||||
void Resize(size_t new_size, T v) {
|
void Resize(size_t new_size, T v) {
|
||||||
if (new_size == Size()) { return; }
|
if (new_size == Size()) { return; }
|
||||||
if (Size() == 0 && device_ >= 0) {
|
if ((Size() == 0 && device_ >= 0) || (DeviceCanWrite() && device_ >= 0)) {
|
||||||
// fast on-device resize
|
// fast on-device resize
|
||||||
gpu_access_ = GPUAccess::kWrite;
|
gpu_access_ = GPUAccess::kWrite;
|
||||||
SetDevice();
|
SetDevice();
|
||||||
data_d_.resize(new_size, v);
|
data_d_->resize(new_size, v);
|
||||||
} else {
|
} else {
|
||||||
// resize on host
|
// resize on host
|
||||||
LazySyncHost(GPUAccess::kNone);
|
LazySyncHost(GPUAccess::kNone);
|
||||||
@ -158,11 +166,11 @@ class HostDeviceVectorImpl {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gpu_access_ = access;
|
gpu_access_ = access;
|
||||||
if (data_h_.size() != data_d_.size()) { data_h_.resize(data_d_.size()); }
|
if (data_h_.size() != data_d_->size()) { data_h_.resize(data_d_->size()); }
|
||||||
SetDevice();
|
SetDevice();
|
||||||
dh::safe_cuda(cudaMemcpy(data_h_.data(),
|
dh::safe_cuda(cudaMemcpy(data_h_.data(),
|
||||||
data_d_.data().get(),
|
data_d_->data().get(),
|
||||||
data_d_.size() * sizeof(T),
|
data_d_->size() * sizeof(T),
|
||||||
cudaMemcpyDeviceToHost));
|
cudaMemcpyDeviceToHost));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,9 +184,9 @@ class HostDeviceVectorImpl {
|
|||||||
// data is on the host
|
// data is on the host
|
||||||
LazyResizeDevice(data_h_.size());
|
LazyResizeDevice(data_h_.size());
|
||||||
SetDevice();
|
SetDevice();
|
||||||
dh::safe_cuda(cudaMemcpy(data_d_.data().get(),
|
dh::safe_cuda(cudaMemcpy(data_d_->data().get(),
|
||||||
data_h_.data(),
|
data_h_.data(),
|
||||||
data_d_.size() * sizeof(T),
|
data_d_->size() * sizeof(T),
|
||||||
cudaMemcpyHostToDevice));
|
cudaMemcpyHostToDevice));
|
||||||
gpu_access_ = access;
|
gpu_access_ = access;
|
||||||
}
|
}
|
||||||
@ -189,11 +197,12 @@ class HostDeviceVectorImpl {
|
|||||||
bool DeviceCanAccess(GPUAccess access) const { return gpu_access_ >= access; }
|
bool DeviceCanAccess(GPUAccess access) const { return gpu_access_ >= access; }
|
||||||
bool DeviceCanRead() const { return DeviceCanAccess(GPUAccess::kRead); }
|
bool DeviceCanRead() const { return DeviceCanAccess(GPUAccess::kRead); }
|
||||||
bool DeviceCanWrite() const { return DeviceCanAccess(GPUAccess::kWrite); }
|
bool DeviceCanWrite() const { return DeviceCanAccess(GPUAccess::kWrite); }
|
||||||
|
GPUAccess Access() const { return gpu_access_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int device_{-1};
|
int device_{-1};
|
||||||
std::vector<T> data_h_{};
|
std::vector<T> data_h_{};
|
||||||
dh::device_vector<T> data_d_{};
|
std::unique_ptr<dh::device_vector<T>> data_d_{};
|
||||||
GPUAccess gpu_access_{GPUAccess::kNone};
|
GPUAccess gpu_access_{GPUAccess::kNone};
|
||||||
|
|
||||||
void CopyToDevice(HostDeviceVectorImpl* other) {
|
void CopyToDevice(HostDeviceVectorImpl* other) {
|
||||||
@ -203,8 +212,8 @@ class HostDeviceVectorImpl {
|
|||||||
LazyResizeDevice(Size());
|
LazyResizeDevice(Size());
|
||||||
gpu_access_ = GPUAccess::kWrite;
|
gpu_access_ = GPUAccess::kWrite;
|
||||||
SetDevice();
|
SetDevice();
|
||||||
dh::safe_cuda(cudaMemcpyAsync(data_d_.data().get(), other->data_d_.data().get(),
|
dh::safe_cuda(cudaMemcpyAsync(data_d_->data().get(), other->data_d_->data().get(),
|
||||||
data_d_.size() * sizeof(T), cudaMemcpyDefault));
|
data_d_->size() * sizeof(T), cudaMemcpyDefault));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,14 +221,14 @@ class HostDeviceVectorImpl {
|
|||||||
LazyResizeDevice(Size());
|
LazyResizeDevice(Size());
|
||||||
gpu_access_ = GPUAccess::kWrite;
|
gpu_access_ = GPUAccess::kWrite;
|
||||||
SetDevice();
|
SetDevice();
|
||||||
dh::safe_cuda(cudaMemcpyAsync(data_d_.data().get(), begin,
|
dh::safe_cuda(cudaMemcpyAsync(data_d_->data().get(), begin,
|
||||||
data_d_.size() * sizeof(T), cudaMemcpyDefault));
|
data_d_->size() * sizeof(T), cudaMemcpyDefault));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LazyResizeDevice(size_t new_size) {
|
void LazyResizeDevice(size_t new_size) {
|
||||||
if (new_size == data_d_.size()) { return; }
|
if (data_d_ && new_size == data_d_->size()) { return; }
|
||||||
SetDevice();
|
SetDevice();
|
||||||
data_d_.resize(new_size);
|
data_d_->resize(new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDevice() {
|
void SetDevice() {
|
||||||
@ -229,6 +238,10 @@ class HostDeviceVectorImpl {
|
|||||||
} else {
|
} else {
|
||||||
(*cudaSetDeviceHandler)(device_);
|
(*cudaSetDeviceHandler)(device_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!data_d_) {
|
||||||
|
data_d_.reset(new dh::device_vector<T>);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -245,16 +258,17 @@ HostDeviceVector<T>::HostDeviceVector(const std::vector<T>& init, int device)
|
|||||||
: impl_(new HostDeviceVectorImpl<T>(init, device)) {}
|
: impl_(new HostDeviceVectorImpl<T>(init, device)) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
HostDeviceVector<T>::HostDeviceVector(const HostDeviceVector<T>& other)
|
HostDeviceVector<T>::HostDeviceVector(HostDeviceVector<T>&& other)
|
||||||
: impl_(new HostDeviceVectorImpl<T>(*other.impl_)) {}
|
: impl_(new HostDeviceVectorImpl<T>(std::move(*other.impl_))) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
HostDeviceVector<T>& HostDeviceVector<T>::operator=(const HostDeviceVector<T>& other) {
|
HostDeviceVector<T>& HostDeviceVector<T>::operator=(HostDeviceVector<T>&& other) {
|
||||||
if (this == &other) { return *this; }
|
if (this == &other) { return *this; }
|
||||||
|
|
||||||
std::unique_ptr<HostDeviceVectorImpl<T>> newImpl(new HostDeviceVectorImpl<T>(*other.impl_));
|
std::unique_ptr<HostDeviceVectorImpl<T>> new_impl(
|
||||||
|
new HostDeviceVectorImpl<T>(std::move(*other.impl_)));
|
||||||
delete impl_;
|
delete impl_;
|
||||||
impl_ = newImpl.release();
|
impl_ = new_impl.release();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,6 +352,11 @@ bool HostDeviceVector<T>::DeviceCanWrite() const {
|
|||||||
return impl_->DeviceCanWrite();
|
return impl_->DeviceCanWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
GPUAccess HostDeviceVector<T>::DeviceAccess() const {
|
||||||
|
return impl_->Access();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void HostDeviceVector<T>::SetDevice(int device) const {
|
void HostDeviceVector<T>::SetDevice(int device) const {
|
||||||
impl_->SetDevice(device);
|
impl_->SetDevice(device);
|
||||||
|
|||||||
@ -339,6 +339,7 @@ class GPUPredictor : public xgboost::Predictor {
|
|||||||
// the first step only modifies prediction store in learner without following code.
|
// the first step only modifies prediction store in learner without following code.
|
||||||
InitOutPredictions(cache_emtry->second.data->Info(),
|
InitOutPredictions(cache_emtry->second.data->Info(),
|
||||||
&(cache_emtry->second.predictions), model);
|
&(cache_emtry->second.predictions), model);
|
||||||
|
CHECK_EQ(cache_emtry->second.predictions.Size(), out_preds->Size());
|
||||||
cache_emtry->second.predictions.Copy(*out_preds);
|
cache_emtry->second.predictions.Copy(*out_preds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,6 +60,7 @@ void PlusOne(HostDeviceVector<int> *v) {
|
|||||||
SetDevice(device);
|
SetDevice(device);
|
||||||
thrust::transform(dh::tcbegin(*v), dh::tcend(*v), dh::tbegin(*v),
|
thrust::transform(dh::tcbegin(*v), dh::tcend(*v), dh::tbegin(*v),
|
||||||
[=]__device__(unsigned int a){ return a + 1; });
|
[=]__device__(unsigned int a){ return a + 1; });
|
||||||
|
ASSERT_TRUE(v->DeviceCanWrite());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckDevice(HostDeviceVector<int>* v,
|
void CheckDevice(HostDeviceVector<int>* v,
|
||||||
@ -125,7 +126,8 @@ TEST(HostDeviceVector, Copy) {
|
|||||||
// a separate scope to ensure that v1 is gone before further checks
|
// a separate scope to ensure that v1 is gone before further checks
|
||||||
HostDeviceVector<int> v1;
|
HostDeviceVector<int> v1;
|
||||||
InitHostDeviceVector(n, device, &v1);
|
InitHostDeviceVector(n, device, &v1);
|
||||||
v = v1;
|
v.Resize(v1.Size());
|
||||||
|
v.Copy(v1);
|
||||||
}
|
}
|
||||||
CheckDevice(&v, n, 0, GPUAccess::kRead);
|
CheckDevice(&v, n, 0, GPUAccess::kRead);
|
||||||
PlusOne(&v);
|
PlusOne(&v);
|
||||||
|
|||||||
@ -11,26 +11,26 @@ TEST(ColumnSampler, Test) {
|
|||||||
|
|
||||||
// No node sampling
|
// No node sampling
|
||||||
cs.Init(n, 1.0f, 0.5f, 0.5f);
|
cs.Init(n, 1.0f, 0.5f, 0.5f);
|
||||||
auto set0 = *cs.GetFeatureSet(0);
|
auto set0 = cs.GetFeatureSet(0);
|
||||||
ASSERT_EQ(set0.Size(), 32);
|
ASSERT_EQ(set0->Size(), 32);
|
||||||
|
|
||||||
auto set1 = *cs.GetFeatureSet(0);
|
auto set1 = cs.GetFeatureSet(0);
|
||||||
|
|
||||||
ASSERT_EQ(set0.HostVector(), set1.HostVector());
|
ASSERT_EQ(set0->HostVector(), set1->HostVector());
|
||||||
|
|
||||||
auto set2 = *cs.GetFeatureSet(1);
|
auto set2 = cs.GetFeatureSet(1);
|
||||||
ASSERT_NE(set1.HostVector(), set2.HostVector());
|
ASSERT_NE(set1->HostVector(), set2->HostVector());
|
||||||
ASSERT_EQ(set2.Size(), 32);
|
ASSERT_EQ(set2->Size(), 32);
|
||||||
|
|
||||||
// Node sampling
|
// Node sampling
|
||||||
cs.Init(n, 0.5f, 1.0f, 0.5f);
|
cs.Init(n, 0.5f, 1.0f, 0.5f);
|
||||||
auto set3 = *cs.GetFeatureSet(0);
|
auto set3 = cs.GetFeatureSet(0);
|
||||||
ASSERT_EQ(set3.Size(), 32);
|
ASSERT_EQ(set3->Size(), 32);
|
||||||
|
|
||||||
auto set4 = *cs.GetFeatureSet(0);
|
auto set4 = cs.GetFeatureSet(0);
|
||||||
|
|
||||||
ASSERT_NE(set3.HostVector(), set4.HostVector());
|
ASSERT_NE(set3->HostVector(), set4->HostVector());
|
||||||
ASSERT_EQ(set4.Size(), 32);
|
ASSERT_EQ(set4->Size(), 32);
|
||||||
|
|
||||||
// No level or node sampling, should be the same at different depth
|
// No level or node sampling, should be the same at different depth
|
||||||
cs.Init(n, 1.0f, 1.0f, 0.5f);
|
cs.Init(n, 1.0f, 1.0f, 0.5f);
|
||||||
@ -38,11 +38,11 @@ TEST(ColumnSampler, Test) {
|
|||||||
cs.GetFeatureSet(1)->HostVector());
|
cs.GetFeatureSet(1)->HostVector());
|
||||||
|
|
||||||
cs.Init(n, 1.0f, 1.0f, 1.0f);
|
cs.Init(n, 1.0f, 1.0f, 1.0f);
|
||||||
auto set5 = *cs.GetFeatureSet(0);
|
auto set5 = cs.GetFeatureSet(0);
|
||||||
ASSERT_EQ(set5.Size(), n);
|
ASSERT_EQ(set5->Size(), n);
|
||||||
cs.Init(n, 1.0f, 1.0f, 1.0f);
|
cs.Init(n, 1.0f, 1.0f, 1.0f);
|
||||||
auto set6 = *cs.GetFeatureSet(0);
|
auto set6 = cs.GetFeatureSet(0);
|
||||||
ASSERT_EQ(set5.HostVector(), set6.HostVector());
|
ASSERT_EQ(set5->HostVector(), set6->HostVector());
|
||||||
|
|
||||||
// Should always be a minimum of one feature
|
// Should always be a minimum of one feature
|
||||||
cs.Init(n, 1e-16f, 1e-16f, 1e-16f);
|
cs.Init(n, 1e-16f, 1e-16f, 1e-16f);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user