File: test_array_interface.cc

package info (click to toggle)
xgboost 3.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 13,796 kB
  • sloc: cpp: 67,502; python: 35,503; java: 4,676; ansic: 1,426; sh: 1,320; xml: 1,197; makefile: 204; javascript: 19
file content (131 lines) | stat: -rw-r--r-- 4,845 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
 * Copyright 2020-2023 by XGBoost Contributors
 */
#include <gtest/gtest.h>
#include <xgboost/host_device_vector.h>
#include "../helpers.h"
#include "../../../src/data/array_interface.h"
#include "dmlc/logging.h"
#include "xgboost/json.h"

namespace xgboost {
TEST(ArrayInterface, Initialize) {
  size_t constexpr kRows = 10, kCols = 10;
  HostDeviceVector<float> storage;
  auto array = RandomDataGenerator{kRows, kCols, 0}.GenerateArrayInterface(&storage);
  auto arr_interface = ArrayInterface<2>(StringView{array});
  ASSERT_EQ(arr_interface.Shape<0>(), kRows);
  ASSERT_EQ(arr_interface.Shape<1>(), kCols);
  ASSERT_EQ(arr_interface.data, storage.ConstHostPointer());
  ASSERT_EQ(arr_interface.ElementSize(), 4);
  ASSERT_EQ(arr_interface.type, ArrayInterfaceHandler::kF4);

  HostDeviceVector<size_t> u64_storage(storage.Size());
  std::string u64_arr_str{ArrayInterfaceStr(linalg::TensorView<size_t const, 2>{
      u64_storage.ConstHostSpan(), {kRows, kCols}, DeviceOrd::CPU()})};
  std::copy(storage.ConstHostVector().cbegin(), storage.ConstHostVector().cend(),
            u64_storage.HostSpan().begin());
  auto u64_arr = ArrayInterface<2>{u64_arr_str};
  ASSERT_EQ(u64_arr.ElementSize(), 8);
  ASSERT_EQ(u64_arr.type, ArrayInterfaceHandler::kU8);
}

TEST(ArrayInterface, Error) {
  constexpr size_t kRows = 16, kCols = 10;
  Json column { Object() };
  std::vector<Json> j_shape {Json(Integer(static_cast<Integer::Int>(kRows)))};
  column["shape"] = Array(j_shape);
  std::vector<Json> j_data{Json(Integer(reinterpret_cast<Integer::Int>(nullptr))),
                           Json(Boolean(false))};

  auto const& column_obj = get<Object>(column);
  std::string typestr{"<f4"};
  size_t n = kRows * kCols;

  // missing version
  EXPECT_THROW(ArrayInterfaceHandler::ExtractData(column_obj, n), dmlc::Error);
  column["version"] = 3;
  // missing data
  EXPECT_THROW(ArrayInterfaceHandler::ExtractData(column_obj, n),
               dmlc::Error);
  // null data
  column["data"] = Null{};
  EXPECT_THROW(ArrayInterfaceHandler::ExtractData(column_obj, n),
               dmlc::Error);
  column["data"] = j_data;
  // missing typestr
  EXPECT_THROW(ArrayInterfaceHandler::ExtractData(column_obj, n),
               dmlc::Error);
  column["typestr"] = String("<f4");
  // nullptr is not valid
  EXPECT_THROW(ArrayInterfaceHandler::ExtractData(column_obj, n),
               dmlc::Error);

  HostDeviceVector<float> storage;
  auto array = RandomDataGenerator{kRows, kCols, 0}.GenerateArrayInterface(&storage);
  j_data = {
      Json(Integer(reinterpret_cast<Integer::Int>(storage.ConstHostPointer()))),
      Json(Boolean(false))};
  column["data"] = j_data;
  EXPECT_NO_THROW(ArrayInterfaceHandler::ExtractData(column_obj, n));
  // null data in mask
  column["mask"] = Object{};
  column["mask"]["data"] = Null{};
  common::Span<RBitField8::value_type> s_mask;
  EXPECT_THROW(ArrayInterfaceHandler::ExtractMask(column_obj, &s_mask), dmlc::Error);

  get<Object>(column).erase("mask");
  // misaligned.
  j_data = {Json(Integer(reinterpret_cast<Integer::Int>(
                reinterpret_cast<char const*>(storage.ConstHostPointer()) + 1))),
            Json(Boolean(false))};
  column["data"] = j_data;
  EXPECT_THROW({ ArrayInterface<1> arr{column}; }, dmlc::Error);
}

TEST(ArrayInterface, GetElement) {
  size_t kRows = 4, kCols = 2;
  HostDeviceVector<float> storage;
  auto intefrace_str = RandomDataGenerator{kRows, kCols, 0}.GenerateArrayInterface(&storage);
  ArrayInterface<2> array_interface{intefrace_str};

  auto const& h_storage = storage.ConstHostVector();
  for (size_t i = 0; i < kRows; ++i) {
    for (size_t j = 0; j < kCols; ++j) {
      float v0 = array_interface(i, j);
      float v1 = h_storage.at(i * kCols + j);
      ASSERT_EQ(v0, v1);
    }
  }
}

TEST(ArrayInterface, TrivialDim) {
  size_t kRows{1000}, kCols = 1;
  HostDeviceVector<float> storage;
  auto interface_str = RandomDataGenerator{kRows, kCols, 0}.GenerateArrayInterface(&storage);
  {
    ArrayInterface<1> arr_i{interface_str};
    ASSERT_EQ(arr_i.n, kRows);
    ASSERT_EQ(arr_i.Shape<0>(), kRows);
  }

  std::swap(kRows, kCols);
  interface_str = RandomDataGenerator{kRows, kCols, 0}.GenerateArrayInterface(&storage);
  {
    ArrayInterface<1> arr_i{interface_str};
    ASSERT_EQ(arr_i.n, kCols);
    ASSERT_EQ(arr_i.Shape<0>(), kCols);
  }
}

TEST(ArrayInterface, ToDType) {
  static_assert(ToDType<float>::kType == ArrayInterfaceHandler::kF4);
  static_assert(ToDType<double>::kType == ArrayInterfaceHandler::kF8);

  static_assert(ToDType<uint32_t>::kType == ArrayInterfaceHandler::kU4);
  static_assert(ToDType<uint64_t>::kType == ArrayInterfaceHandler::kU8);

  static_assert(ToDType<int32_t>::kType == ArrayInterfaceHandler::kI4);
  static_assert(ToDType<int64_t>::kType == ArrayInterfaceHandler::kI8);
}
}  // namespace xgboost