Implement fast number serialization routines. (#5772)
* Implement ryu algorithm. * Implement integer printing. * Full coverage roundtrip test.
This commit is contained in:
213
tests/cpp/common/test_charconv.cc
Normal file
213
tests/cpp/common/test_charconv.cc
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* The code is adopted from original (half) c implementation:
|
||||
* https://github.com/ulfjack/ryu.git with some more comments and tidying. License is
|
||||
* attached below.
|
||||
*
|
||||
* Copyright 2018 Ulf Adams
|
||||
*
|
||||
* The contents of this file may be used under the terms of the Apache License,
|
||||
* Version 2.0.
|
||||
*
|
||||
* (See accompanying file LICENSE-Apache or copy at
|
||||
* http: *www.apache.org/licenses/LICENSE-2.0)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE-Boost or copy at
|
||||
* https://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, this software
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <gtest/gtest.h>
|
||||
#include <limits>
|
||||
#include "../../../src/common/charconv.h"
|
||||
|
||||
namespace xgboost {
|
||||
namespace {
|
||||
void TestInteger(char const* res, int64_t i) {
|
||||
char result[xgboost::NumericLimits<int64_t>::kToCharsSize];
|
||||
auto ret = to_chars(result, result + sizeof(result), i);
|
||||
*ret.ptr = '\0';
|
||||
EXPECT_STREQ(res, result);
|
||||
}
|
||||
|
||||
static float Int32Bits2Float(uint32_t bits) {
|
||||
float f;
|
||||
memcpy(&f, &bits, sizeof(float));
|
||||
return f;
|
||||
}
|
||||
|
||||
void TestRyu(char const *res, float v) {
|
||||
char result[xgboost::NumericLimits<float>::kToCharsSize];
|
||||
auto ret = to_chars(result, result + sizeof(result), v);
|
||||
*ret.ptr = '\0';
|
||||
EXPECT_STREQ(res, result);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
TEST(Ryu, Subnormal) {
|
||||
TestRyu("0E0", 0.0f);
|
||||
TestRyu("-0E0", -0.0f);
|
||||
TestRyu("1E0", 1.0f);
|
||||
TestRyu("-1E0", -1.0f);
|
||||
TestRyu("NaN", NAN);
|
||||
TestRyu("Infinity", INFINITY);
|
||||
TestRyu("-Infinity", -INFINITY);
|
||||
|
||||
TestRyu("1E-45", std::numeric_limits<float>::denorm_min());
|
||||
}
|
||||
|
||||
TEST(Ryu, Denormal) {
|
||||
TestRyu("1E-45", std::numeric_limits<float>::denorm_min());
|
||||
}
|
||||
|
||||
TEST(Ryu, SwitchToSubnormal) {
|
||||
TestRyu("1.1754944E-38", 1.1754944E-38f);
|
||||
}
|
||||
|
||||
TEST(Ryu, MinAndMax) {
|
||||
TestRyu("3.4028235E38", Int32Bits2Float(0x7f7fffff));
|
||||
TestRyu("1E-45", Int32Bits2Float(1));
|
||||
}
|
||||
|
||||
// Check that we return the exact boundary if it is the shortest
|
||||
// representation, but only if the original floating point number is even.
|
||||
TEST(Ryu, BoundaryRoundEven) {
|
||||
TestRyu("3.355445E7", 3.355445E7f);
|
||||
TestRyu("9E9", 8.999999E9f);
|
||||
TestRyu("3.436672E10", 3.4366717E10f);
|
||||
}
|
||||
|
||||
// If the exact value is exactly halfway between two shortest representations,
|
||||
// then we round to even. It seems like this only makes a difference if the
|
||||
// last two digits are ...2|5 or ...7|5, and we cut off the 5.
|
||||
TEST(Ryu, ExactValueRoundEven) {
|
||||
TestRyu("3.0540412E5", 3.0540412E5f);
|
||||
TestRyu("8.0990312E3", 8.0990312E3f);
|
||||
}
|
||||
|
||||
TEST(Ryu, LotsOfTrailingZeros) {
|
||||
// Pattern for the first test: 00111001100000000000000000000000
|
||||
TestRyu("2.4414062E-4", 2.4414062E-4f);
|
||||
TestRyu("2.4414062E-3", 2.4414062E-3f);
|
||||
TestRyu("4.3945312E-3", 4.3945312E-3f);
|
||||
TestRyu("6.3476562E-3", 6.3476562E-3f);
|
||||
}
|
||||
|
||||
TEST(Ryu, Regression) {
|
||||
TestRyu("4.7223665E21", 4.7223665E21f);
|
||||
TestRyu("8.388608E6", 8388608.0f);
|
||||
TestRyu("1.6777216E7", 1.6777216E7f);
|
||||
TestRyu("3.3554436E7", 3.3554436E7f);
|
||||
TestRyu("6.7131496E7", 6.7131496E7f);
|
||||
TestRyu("1.9310392E-38", 1.9310392E-38f);
|
||||
TestRyu("-2.47E-43", -2.47E-43f);
|
||||
TestRyu("1.993244E-38", 1.993244E-38f);
|
||||
TestRyu("4.1039004E3", 4103.9003f);
|
||||
TestRyu("5.3399997E9", 5.3399997E9f);
|
||||
TestRyu("6.0898E-39", 6.0898E-39f);
|
||||
TestRyu("1.0310042E-3", 0.0010310042f);
|
||||
TestRyu("2.882326E17", 2.8823261E17f);
|
||||
TestRyu("7.038531E-26", 7.0385309E-26f);
|
||||
TestRyu("9.223404E17", 9.2234038E17f);
|
||||
TestRyu("6.710887E7", 6.7108872E7f);
|
||||
TestRyu("1E-44", 1.0E-44f);
|
||||
TestRyu("2.816025E14", 2.816025E14f);
|
||||
TestRyu("9.223372E18", 9.223372E18f);
|
||||
TestRyu("1.5846086E29", 1.5846085E29f);
|
||||
TestRyu("1.1811161E19", 1.1811161E19f);
|
||||
TestRyu("5.368709E18", 5.368709E18f);
|
||||
TestRyu("4.6143166E18", 4.6143165E18f);
|
||||
TestRyu("7.812537E-3", 0.007812537f);
|
||||
TestRyu("1E-45", 1.4E-45f);
|
||||
TestRyu("1.18697725E20", 1.18697724E20f);
|
||||
TestRyu("1.00014165E-36", 1.00014165E-36f);
|
||||
TestRyu("2E2", 200.0f);
|
||||
TestRyu("3.3554432E7", 3.3554432E7f);
|
||||
|
||||
static_assert(1.1920929E-7f == std::numeric_limits<float>::epsilon(), "");
|
||||
TestRyu("1.1920929E-7", std::numeric_limits<float>::epsilon());
|
||||
}
|
||||
|
||||
TEST(Ryu, RoundTrip) {
|
||||
float f = -1.1493590134238582e-40;
|
||||
char result[NumericLimits<float>::kToCharsSize] { 0 };
|
||||
auto ret = to_chars(result, result + sizeof(result), f);
|
||||
size_t dis = std::distance(result, ret.ptr);
|
||||
float back;
|
||||
auto from_ret = from_chars(result, result + dis, back);
|
||||
ASSERT_EQ(from_ret.ec, std::errc());
|
||||
std::string str;
|
||||
for (size_t i = 0; i < dis; ++i) {
|
||||
str.push_back(result[i]);
|
||||
}
|
||||
ASSERT_EQ(f, back);
|
||||
}
|
||||
|
||||
TEST(Ryu, LooksLikePow5) {
|
||||
// These numbers have a mantissa that is the largest power of 5 that fits,
|
||||
// and an exponent that causes the computation for q to result in 10, which is a corner
|
||||
// case for Ryu.
|
||||
TestRyu("6.7108864E17", Int32Bits2Float(0x5D1502F9));
|
||||
TestRyu("1.3421773E18", Int32Bits2Float(0x5D9502F9));
|
||||
TestRyu("2.6843546E18", Int32Bits2Float(0x5E1502F9));
|
||||
}
|
||||
|
||||
TEST(Ryu, OutputLength) {
|
||||
TestRyu("1E0", 1.0f); // already tested in Basic
|
||||
TestRyu("1.2E0", 1.2f);
|
||||
TestRyu("1.23E0", 1.23f);
|
||||
TestRyu("1.234E0", 1.234f);
|
||||
TestRyu("1.2345E0", 1.2345f);
|
||||
TestRyu("1.23456E0", 1.23456f);
|
||||
TestRyu("1.234567E0", 1.234567f);
|
||||
TestRyu("1.2345678E0", 1.2345678f);
|
||||
TestRyu("1.23456735E-36", 1.23456735E-36f);
|
||||
}
|
||||
|
||||
TEST(IntegerPrinting, Basic) {
|
||||
TestInteger("0", 0);
|
||||
auto str = std::to_string(std::numeric_limits<int64_t>::min());
|
||||
TestInteger(str.c_str(), std::numeric_limits<int64_t>::min());
|
||||
str = std::to_string(std::numeric_limits<int64_t>::max());
|
||||
TestInteger(str.c_str(), std::numeric_limits<int64_t>::max());
|
||||
}
|
||||
|
||||
void TestRyuParse(float f, std::string in) {
|
||||
float res;
|
||||
auto ret = from_chars(in.c_str(), in.c_str() + in.size(), res);
|
||||
ASSERT_EQ(ret.ec, std::errc());
|
||||
ASSERT_EQ(f, res);
|
||||
}
|
||||
|
||||
TEST(Ryu, Basic) {
|
||||
TestRyuParse(0.0f, "0");
|
||||
TestRyuParse(-0.0f, "-0");
|
||||
TestRyuParse(1.0f, "1");
|
||||
TestRyuParse(-1.0f, "-1");
|
||||
TestRyuParse(123456792.0f, "123456789");
|
||||
TestRyuParse(299792448.0f, "299792458");
|
||||
}
|
||||
|
||||
TEST(Ryu, MinMax) {
|
||||
TestRyuParse(1e-45f, "1e-45");
|
||||
TestRyuParse(FLT_MIN, "1.1754944e-38");
|
||||
TestRyuParse(FLT_MAX, "3.4028235e+38");
|
||||
}
|
||||
|
||||
TEST(Ryu, MantissaRoundingOverflow) {
|
||||
TestRyuParse(1.0f, "0.999999999");
|
||||
TestRyuParse(INFINITY, "3.4028236e+38");
|
||||
TestRyuParse(1.1754944e-38f, "1.17549430e-38"); // FLT_MIN
|
||||
}
|
||||
|
||||
TEST(Ryu, TrailingZeros) {
|
||||
TestRyuParse(26843550.0f, "26843549.5");
|
||||
TestRyuParse(50000004.0f, "50000002.5");
|
||||
TestRyuParse(99999992.0f, "99999989.5");
|
||||
}
|
||||
|
||||
} // namespace xgboost
|
||||
@@ -248,9 +248,9 @@ TEST(HistUtil, AdapterDeviceSketch) {
|
||||
thrust::device_vector< float> data(rows*cols);
|
||||
auto json_array_interface = Generate2dArrayInterface(rows, cols, "<f4", &data);
|
||||
data = std::vector<float >{ 1.0,2.0,3.0,4.0,5.0 };
|
||||
std::stringstream ss;
|
||||
Json::Dump(json_array_interface, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(json_array_interface, &str);
|
||||
|
||||
data::CupyAdapter adapter(str);
|
||||
|
||||
auto device_cuts = AdapterDeviceSketch(&adapter, num_bins, missing);
|
||||
|
||||
@@ -54,9 +54,8 @@ inline data::CupyAdapter AdapterFromData(const thrust::device_vector<float> &x,
|
||||
array_interface["data"] = j_data;
|
||||
array_interface["version"] = Integer(static_cast<Integer::Int>(1));
|
||||
array_interface["typestr"] = String("<f4");
|
||||
std::stringstream ss;
|
||||
Json::Dump(array_interface, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(array_interface, &str);
|
||||
return data::CupyAdapter(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
#include "xgboost/json.h"
|
||||
#include "xgboost/logging.h"
|
||||
#include "xgboost/json_io.h"
|
||||
#include "../helpers.h"
|
||||
#include "../../../src/common/io.h"
|
||||
#include "../../../src/common/charconv.h"
|
||||
|
||||
namespace xgboost {
|
||||
|
||||
@@ -146,22 +148,46 @@ TEST(Json, ParseNumber) {
|
||||
{
|
||||
std::string str = "31.8892";
|
||||
auto json = Json::Load(StringView{str.c_str(), str.size()});
|
||||
ASSERT_NEAR(get<JsonNumber>(json), 31.8892f, kRtEps);
|
||||
ASSERT_EQ(get<JsonNumber>(json), 31.8892f);
|
||||
}
|
||||
{
|
||||
std::string str = "-31.8892";
|
||||
auto json = Json::Load(StringView{str.c_str(), str.size()});
|
||||
ASSERT_NEAR(get<JsonNumber>(json), -31.8892f, kRtEps);
|
||||
ASSERT_EQ(get<JsonNumber>(json), -31.8892f);
|
||||
}
|
||||
{
|
||||
std::string str = "2e4";
|
||||
auto json = Json::Load(StringView{str.c_str(), str.size()});
|
||||
ASSERT_NEAR(get<JsonNumber>(json), 2e4f, kRtEps);
|
||||
ASSERT_EQ(get<JsonNumber>(json), 2e4f);
|
||||
}
|
||||
{
|
||||
std::string str = "2e-4";
|
||||
auto json = Json::Load(StringView{str.c_str(), str.size()});
|
||||
ASSERT_NEAR(get<JsonNumber>(json), 2e-4f, kRtEps);
|
||||
ASSERT_EQ(get<JsonNumber>(json), 2e-4f);
|
||||
}
|
||||
{
|
||||
std::string str = "-2e-4";
|
||||
auto json = Json::Load(StringView{str.c_str(), str.size()});
|
||||
ASSERT_EQ(get<JsonNumber>(json), -2e-4f);
|
||||
}
|
||||
{
|
||||
std::string str = "-0.0";
|
||||
auto json = Json::Load(StringView{str.c_str(), str.size()});
|
||||
ASSERT_TRUE(std::signbit(get<JsonNumber>(json)));
|
||||
ASSERT_EQ(get<JsonNumber>(json), -0);
|
||||
}
|
||||
{
|
||||
std::string str = "-5.37645816802978516e-01";
|
||||
auto json = Json::Load(StringView{str.c_str(), str.size()});
|
||||
ASSERT_TRUE(std::signbit(get<JsonNumber>(json)));
|
||||
// Larger than fast path limit.
|
||||
ASSERT_EQ(get<JsonNumber>(json), -5.37645816802978516e-01);
|
||||
}
|
||||
{
|
||||
std::string str = "9.86623668670654297e+00";
|
||||
auto json = Json::Load(StringView{str.c_str(), str.size()});
|
||||
ASSERT_FALSE(std::signbit(get<JsonNumber>(json)));
|
||||
ASSERT_EQ(get<JsonNumber>(json), 9.86623668670654297e+00);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,13 +226,30 @@ TEST(Json, ParseArray) {
|
||||
Json v0 = arr[0];
|
||||
ASSERT_EQ(get<Integer>(v0["depth"]), 3);
|
||||
ASSERT_NEAR(get<Number>(v0["gain"]), 10.4866, kRtEps);
|
||||
|
||||
{
|
||||
std::string str =
|
||||
"[5.04713470458984375e+02,9.86623668670654297e+00,4.94847229003906250e+"
|
||||
"02,2.13924217224121094e+00,7.72699451446533203e+00,2."
|
||||
"30380615234375000e+02,2.64466613769531250e+02]";
|
||||
auto json = Json::Load(StringView{str.c_str(), str.size()});
|
||||
|
||||
auto const& vec = get<Array const>(json);
|
||||
ASSERT_EQ(get<Number const>(vec[0]), 5.04713470458984375e+02);
|
||||
ASSERT_EQ(get<Number const>(vec[1]), 9.86623668670654297e+00);
|
||||
ASSERT_EQ(get<Number const>(vec[2]), 4.94847229003906250e+02);
|
||||
ASSERT_EQ(get<Number const>(vec[3]), 2.13924217224121094e+00);
|
||||
ASSERT_EQ(get<Number const>(vec[4]), 7.72699451446533203e+00);
|
||||
ASSERT_EQ(get<Number const>(vec[5]), 2.30380615234375000e+02);
|
||||
ASSERT_EQ(get<Number const>(vec[6]), 2.64466613769531250e+02);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Json, Null) {
|
||||
Json json {JsonNull()};
|
||||
std::stringstream ss;
|
||||
std::string ss;
|
||||
Json::Dump(json, &ss);
|
||||
ASSERT_EQ(ss.str(), "null");
|
||||
ASSERT_EQ(ss, "null");
|
||||
|
||||
std::string null_input {R"null({"key": null })null"};
|
||||
|
||||
@@ -288,7 +331,7 @@ TEST(Json, AssigningObjects) {
|
||||
Json json_object { JsonObject() };
|
||||
auto str = JsonString("1");
|
||||
auto& k = json_object["1"];
|
||||
k = str;
|
||||
k = std::move(str);
|
||||
auto& m = json_object["1"];
|
||||
std::string value = get<JsonString>(m);
|
||||
ASSERT_EQ(value, "1");
|
||||
@@ -365,15 +408,56 @@ TEST(Json, LoadDump) {
|
||||
dmlc::TemporaryDirectory tempdir;
|
||||
auto const& path = tempdir.path + "test_model_dump";
|
||||
|
||||
std::ofstream fout (path);
|
||||
Json::Dump(origin, &fout);
|
||||
fout.close();
|
||||
std::string out;
|
||||
Json::Dump(origin, &out);
|
||||
|
||||
std::ofstream fout(path);
|
||||
ASSERT_TRUE(fout);
|
||||
fout << out << std::flush;
|
||||
|
||||
std::string new_buffer = common::LoadSequentialFile(path);
|
||||
Json load_back {Json::Load(StringView(new_buffer.c_str(), new_buffer.size()))};
|
||||
|
||||
ASSERT_EQ(load_back, origin) << ori_buffer << "\n\n---------------\n\n"
|
||||
<< new_buffer;
|
||||
Json load_back {Json::Load(StringView(new_buffer.c_str(), new_buffer.size()))};
|
||||
ASSERT_EQ(load_back, origin);
|
||||
}
|
||||
|
||||
TEST(Json, Invalid) {
|
||||
{
|
||||
std::string str = "}";
|
||||
bool has_thrown = false;
|
||||
try {
|
||||
Json load{Json::Load(StringView(str.c_str(), str.size()))};
|
||||
} catch (dmlc::Error const &e) {
|
||||
std::string msg = e.what();
|
||||
ASSERT_NE(msg.find("Unknown"), std::string::npos);
|
||||
has_thrown = true;
|
||||
};
|
||||
ASSERT_TRUE(has_thrown);
|
||||
}
|
||||
{
|
||||
std::string str = R"json({foo)json";
|
||||
bool has_thrown = false;
|
||||
try {
|
||||
Json load{Json::Load(StringView(str.c_str(), str.size()))};
|
||||
} catch (dmlc::Error const &e) {
|
||||
std::string msg = e.what();
|
||||
ASSERT_NE(msg.find("position: 1"), std::string::npos);
|
||||
has_thrown = true;
|
||||
};
|
||||
ASSERT_TRUE(has_thrown);
|
||||
}
|
||||
{
|
||||
std::string str = R"json({"foo")json";
|
||||
bool has_thrown = false;
|
||||
try {
|
||||
Json load{Json::Load(StringView(str.c_str(), str.size()))};
|
||||
} catch (dmlc::Error const &e) {
|
||||
std::string msg = e.what();
|
||||
ASSERT_NE(msg.find("EOF"), std::string::npos);
|
||||
has_thrown = true;
|
||||
};
|
||||
ASSERT_TRUE(has_thrown);
|
||||
}
|
||||
}
|
||||
|
||||
// For now Json is quite ignorance about unicode.
|
||||
@@ -383,10 +467,9 @@ TEST(Json, CopyUnicode) {
|
||||
)json";
|
||||
Json loaded {Json::Load(StringView{json_str.c_str(), json_str.size()})};
|
||||
|
||||
std::stringstream ss_1;
|
||||
Json::Dump(loaded, &ss_1);
|
||||
std::string dumped_string;
|
||||
Json::Dump(loaded, &dumped_string);
|
||||
|
||||
std::string dumped_string = ss_1.str();
|
||||
ASSERT_NE(dumped_string.find("\\u20ac"), std::string::npos);
|
||||
}
|
||||
|
||||
@@ -406,6 +489,15 @@ TEST(Json, WrongCasts) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Json, Integer) {
|
||||
for (int64_t i = 1; i < 10000; i *= 10) {
|
||||
auto ten = Json{Integer{i}};
|
||||
std::string str;
|
||||
Json::Dump(ten, &str);
|
||||
ASSERT_EQ(str, std::to_string(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Json, IntVSFloat) {
|
||||
// If integer is parsed as float, calling `get<Integer>()' will throw.
|
||||
{
|
||||
@@ -432,4 +524,31 @@ TEST(Json, IntVSFloat) {
|
||||
ASSERT_EQ(ptr, 2503595760);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Json, RoundTrip) {
|
||||
uint32_t i = 0;
|
||||
SimpleLCG rng;
|
||||
SimpleRealUniformDistribution<float> dist(1.0f, 4096.0f);
|
||||
|
||||
while (i <= std::numeric_limits<uint32_t>::max()) {
|
||||
float f;
|
||||
std::memcpy(&f, &i, sizeof(f));
|
||||
|
||||
Json jf { f };
|
||||
std::string str;
|
||||
Json::Dump(jf, &str);
|
||||
auto loaded = Json::Load({str.c_str(), str.size()});
|
||||
if (XGBOOST_EXPECT(std::isnan(f), false)) {
|
||||
ASSERT_TRUE(std::isnan(get<Number const>(loaded)));
|
||||
} else {
|
||||
ASSERT_EQ(get<Number const>(loaded), f);
|
||||
}
|
||||
|
||||
auto t = i;
|
||||
i+= static_cast<uint32_t>(dist(&rng));
|
||||
if (i < t) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace xgboost
|
||||
|
||||
@@ -50,7 +50,7 @@ __global__ void TestFromOtherKernel(Span<float> span) {
|
||||
}
|
||||
}
|
||||
// Test converting different T
|
||||
__global__ void TestFromOtherKernelConst(Span<float const, 16> span) {
|
||||
__global__ void TestFromOtherKernelConst(Span<float const, 16> span) {
|
||||
// don't get optimized out
|
||||
size_t idx = threadIdx.x + blockIdx.x * blockDim.x;
|
||||
|
||||
|
||||
@@ -23,9 +23,8 @@ void TestCudfAdapter()
|
||||
|
||||
Json column_arr {columns};
|
||||
|
||||
std::stringstream ss;
|
||||
Json::Dump(column_arr, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(column_arr, &str);
|
||||
|
||||
data::CudfAdapter adapter(str);
|
||||
|
||||
|
||||
@@ -78,9 +78,8 @@ TEST(DeviceDMatrix, ColumnMajor) {
|
||||
|
||||
Json column_arr{columns};
|
||||
|
||||
std::stringstream ss;
|
||||
Json::Dump(column_arr, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(column_arr, &str);
|
||||
|
||||
data::CudfAdapter adapter(str);
|
||||
data::DeviceDMatrix dmat(&adapter, std::numeric_limits<float>::quiet_NaN(),
|
||||
|
||||
@@ -32,9 +32,8 @@ std::string PrepareData(std::string typestr, thrust::device_vector<T>* out, cons
|
||||
column["data"] = j_data;
|
||||
Json array(std::vector<Json>{column});
|
||||
|
||||
std::stringstream ss;
|
||||
Json::Dump(array, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(array, &str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -22,9 +22,8 @@ TEST(SimpleDMatrix, FromColumnarDenseBasic) {
|
||||
|
||||
Json column_arr{columns};
|
||||
|
||||
std::stringstream ss;
|
||||
Json::Dump(column_arr, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(column_arr, &str);
|
||||
|
||||
data::CudfAdapter adapter(str);
|
||||
data::SimpleDMatrix dmat(&adapter, std::numeric_limits<float>::quiet_NaN(),
|
||||
@@ -59,9 +58,8 @@ TEST(SimpleDMatrix, FromColumnarDense) {
|
||||
|
||||
Json column_arr{columns};
|
||||
|
||||
std::stringstream ss;
|
||||
Json::Dump(column_arr, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(column_arr, &str);
|
||||
|
||||
// no missing value
|
||||
{
|
||||
@@ -156,9 +154,9 @@ TEST(SimpleDMatrix, FromColumnarWithEmptyRows) {
|
||||
}
|
||||
|
||||
Json column_arr{Array(v_columns)};
|
||||
std::stringstream ss;
|
||||
Json::Dump(column_arr, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(column_arr, &str);
|
||||
|
||||
data::CudfAdapter adapter(str);
|
||||
data::SimpleDMatrix dmat(&adapter, std::numeric_limits<float>::quiet_NaN(),
|
||||
-1);
|
||||
@@ -244,9 +242,8 @@ TEST(SimpleCSRSource, FromColumnarSparse) {
|
||||
|
||||
Json column_arr {Array(j_columns)};
|
||||
|
||||
std::stringstream ss;
|
||||
Json::Dump(column_arr, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(column_arr, &str);
|
||||
|
||||
{
|
||||
data::CudfAdapter adapter(str);
|
||||
@@ -296,9 +293,8 @@ TEST(SimpleDMatrix, FromColumnarSparseBasic) {
|
||||
|
||||
Json column_arr{columns};
|
||||
|
||||
std::stringstream ss;
|
||||
Json::Dump(column_arr, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(column_arr, &str);
|
||||
|
||||
data::CudfAdapter adapter(str);
|
||||
data::SimpleDMatrix dmat(&adapter, std::numeric_limits<float>::quiet_NaN(),
|
||||
@@ -324,9 +320,8 @@ TEST(SimpleDMatrix, FromCupy){
|
||||
int cols = 10;
|
||||
thrust::device_vector< float> data(rows*cols);
|
||||
auto json_array_interface = Generate2dArrayInterface(rows, cols, "<f4", &data);
|
||||
std::stringstream ss;
|
||||
Json::Dump(json_array_interface, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(json_array_interface, &str);
|
||||
data::CupyAdapter adapter(str);
|
||||
data::SimpleDMatrix dmat(&adapter, -1, 1);
|
||||
EXPECT_EQ(dmat.Info().num_col_, cols);
|
||||
@@ -351,9 +346,8 @@ TEST(SimpleDMatrix, FromCupySparse){
|
||||
auto json_array_interface = Generate2dArrayInterface(rows, cols, "<f4", &data);
|
||||
data[1] = std::numeric_limits<float>::quiet_NaN();
|
||||
data[2] = std::numeric_limits<float>::quiet_NaN();
|
||||
std::stringstream ss;
|
||||
Json::Dump(json_array_interface, &ss);
|
||||
std::string str = ss.str();
|
||||
std::string str;
|
||||
Json::Dump(json_array_interface, &str);
|
||||
data::CupyAdapter adapter(str);
|
||||
data::SimpleDMatrix dmat(&adapter, -1, 1);
|
||||
EXPECT_EQ(dmat.Info().num_col_, cols);
|
||||
|
||||
Reference in New Issue
Block a user