Skip to content

Commit 78aaac3

Browse files
Implement grid view (#2346)
Implemented xchunk_iterator, separate xchunked_view
1 parent 40ddbfc commit 78aaac3

File tree

4 files changed

+265
-1
lines changed

4 files changed

+265
-1
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ set(XTENSOR_HEADERS
124124
${XTENSOR_INCLUDE_DIR}/xtensor/xbuffer_adaptor.hpp
125125
${XTENSOR_INCLUDE_DIR}/xtensor/xbuilder.hpp
126126
${XTENSOR_INCLUDE_DIR}/xtensor/xchunked_array.hpp
127+
${XTENSOR_INCLUDE_DIR}/xtensor/xchunked_view.hpp
127128
${XTENSOR_INCLUDE_DIR}/xtensor/xcomplex.hpp
128129
${XTENSOR_INCLUDE_DIR}/xtensor/xcontainer.hpp
129130
${XTENSOR_INCLUDE_DIR}/xtensor/xcsv.hpp

include/xtensor/xchunked_view.hpp

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/***************************************************************************
2+
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
3+
* Copyright (c) QuantStack *
4+
* *
5+
* Distributed under the terms of the BSD 3-Clause License. *
6+
* *
7+
* The full license is in the file LICENSE, distributed with this software. *
8+
****************************************************************************/
9+
10+
#ifndef XTENSOR_CHUNKED_VIEW_HPP
11+
#define XTENSOR_CHUNKED_VIEW_HPP
12+
13+
#include "xstrided_view.hpp"
14+
#include "xnoalias.hpp"
15+
16+
namespace xt
17+
{
18+
19+
template <class E>
20+
class xchunked_view;
21+
22+
template <class E>
23+
class xchunk_iterator
24+
{
25+
public:
26+
xchunk_iterator(xchunked_view<E>& chunked_view, std::size_t chunk_idx);
27+
xchunk_iterator() = default;
28+
29+
xchunk_iterator<E>& operator++();
30+
xchunk_iterator<E> operator++(int);
31+
bool operator==(const xchunk_iterator& other) const;
32+
bool operator!=(const xchunk_iterator& other) const;
33+
auto operator*();
34+
35+
private:
36+
xchunked_view<E>* m_pcv;
37+
std::size_t m_ci;
38+
};
39+
40+
template <class E>
41+
class xchunked_view
42+
{
43+
public:
44+
template <class OE>
45+
xchunked_view(OE&& e, std::vector<std::size_t>& chunk_shape);
46+
47+
xchunk_iterator<E> begin();
48+
xchunk_iterator<E> end();
49+
50+
template <class OE>
51+
xchunked_view<E>& operator=(const OE& e);
52+
53+
private:
54+
E m_expression;
55+
std::vector<std::size_t> m_shape;
56+
std::vector<std::size_t> m_chunk_shape;
57+
std::vector<std::size_t> m_shape_of_chunks;
58+
std::vector<std::size_t> m_ic;
59+
std::size_t m_chunk_nb;
60+
xstrided_slice_vector m_sv;
61+
62+
friend class xchunk_iterator<E>;
63+
};
64+
65+
template <class E>
66+
inline xchunk_iterator<E>::xchunk_iterator(xchunked_view<E>& chunked_view, std::size_t chunk_idx)
67+
: m_pcv(&chunked_view)
68+
, m_ci(chunk_idx)
69+
{
70+
}
71+
72+
template <class E>
73+
inline xchunk_iterator<E>& xchunk_iterator<E>::operator++()
74+
{
75+
if (m_ci != m_pcv->m_chunk_nb - 1)
76+
{
77+
std::size_t di = m_pcv->m_shape.size() - 1;
78+
while (true)
79+
{
80+
if (m_pcv->m_ic[di] + 1 == m_pcv->m_shape_of_chunks[di])
81+
{
82+
m_pcv->m_ic[di] = 0;
83+
m_pcv->m_sv[di] = range(0, m_pcv->m_chunk_shape[di]);
84+
if (di == 0)
85+
{
86+
break;
87+
}
88+
else
89+
{
90+
di--;
91+
}
92+
}
93+
else
94+
{
95+
m_pcv->m_ic[di] += 1;
96+
m_pcv->m_sv[di] = range(m_pcv->m_ic[di] * m_pcv->m_chunk_shape[di], (m_pcv->m_ic[di] + 1) * m_pcv->m_chunk_shape[di]);
97+
break;
98+
}
99+
}
100+
}
101+
m_ci++;
102+
return *this;
103+
}
104+
105+
template <class E>
106+
inline xchunk_iterator<E> xchunk_iterator<E>::operator++(int)
107+
{
108+
xchunk_iterator<E> it = *this;
109+
++(*this);
110+
return it;
111+
}
112+
113+
template <class E>
114+
inline bool xchunk_iterator<E>::operator==(const xchunk_iterator& other) const
115+
{
116+
return m_ci == other.m_ci;
117+
}
118+
119+
template <class E>
120+
inline bool xchunk_iterator<E>::operator!=(const xchunk_iterator& other) const
121+
{
122+
return !(*this == other);
123+
}
124+
125+
template <class E>
126+
inline auto xchunk_iterator<E>::operator*()
127+
{
128+
auto chunk = strided_view(m_pcv->m_expression, m_pcv->m_sv);
129+
return std::make_pair(chunk, m_pcv->m_sv);
130+
}
131+
132+
template <class E>
133+
template <class OE>
134+
inline xchunked_view<E>::xchunked_view(OE&& e, std::vector<std::size_t>& chunk_shape)
135+
: m_expression(std::forward<OE>(e))
136+
, m_chunk_shape(chunk_shape)
137+
{
138+
m_shape.resize(e.dimension());
139+
const auto& s = e.shape();
140+
std::copy(s.cbegin(), s.cend(), m_shape.begin());
141+
// compute chunk number in each dimension
142+
m_shape_of_chunks.resize(m_shape.size());
143+
std::transform
144+
(
145+
m_shape.cbegin(), m_shape.cend(),
146+
m_chunk_shape.cbegin(),
147+
m_shape_of_chunks.begin(),
148+
[](auto s, auto cs)
149+
{
150+
std::size_t cn = s / cs;
151+
if (s % cs > 0)
152+
{
153+
cn++; // edge_chunk
154+
}
155+
return cn;
156+
}
157+
);
158+
m_ic.resize(m_shape.size());
159+
m_chunk_nb = std::accumulate(std::begin(m_shape_of_chunks), std::end(m_shape_of_chunks), std::size_t(1), std::multiplies<>());
160+
m_sv.resize(m_shape.size());
161+
}
162+
163+
template <class E>
164+
inline xchunk_iterator<E> xchunked_view<E>::begin()
165+
{
166+
auto it = xchunk_iterator<E>(*this, 0);
167+
std::transform(m_chunk_shape.begin(), m_chunk_shape.end(), m_sv.begin(),
168+
[](auto size) { return range(0, size); });
169+
std::fill(m_ic.begin(), m_ic.end(), std::size_t(0));
170+
return it;
171+
}
172+
173+
template <class E>
174+
inline xchunk_iterator<E> xchunked_view<E>::end()
175+
{
176+
auto it = xchunk_iterator<E>(*this, m_chunk_nb);
177+
return it;
178+
}
179+
180+
template <class E>
181+
template <class OE>
182+
xchunked_view<E>& xchunked_view<E>::operator=(const OE& e)
183+
{
184+
for (auto it = begin(); it != end(); it++)
185+
{
186+
auto el = *it;
187+
noalias(el.first) = strided_view(e, el.second);
188+
}
189+
return *this;
190+
}
191+
192+
template <class E>
193+
auto as_chunked(E&& e, std::vector<std::size_t>& chunk_shape)
194+
{
195+
return xchunked_view<E>(std::forward<E>(e), chunk_shape);
196+
}
197+
198+
}
199+
200+
#endif

test/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ set(XTENSOR_TESTS
205205
test_xaxis_iterator.cpp
206206
test_xaxis_slice_iterator.cpp
207207
test_xbuffer_adaptor.cpp
208+
test_xchunked_array.cpp
209+
test_xchunked_view.cpp
208210
test_xcomplex.cpp
209211
test_xcsv.cpp
210212
test_xdatesupport.cpp
@@ -238,7 +240,6 @@ set(XTENSOR_TESTS
238240
test_extended_xmath_reducers.cpp
239241
test_extended_xhistogram.cpp
240242
test_extended_xsort.cpp
241-
test_xchunked_array.cpp
242243
test_sfinae.cpp
243244
)
244245

test/test_xchunked_view.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/***************************************************************************
2+
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
3+
* Copyright (c) QuantStack *
4+
* *
5+
* Distributed under the terms of the BSD 3-Clause License. *
6+
* *
7+
* The full license is in the file LICENSE, distributed with this software. *
8+
****************************************************************************/
9+
10+
#include "gtest/gtest.h"
11+
#include "xtensor/xarray.hpp"
12+
#include "xtensor/xchunked_array.hpp"
13+
#include "xtensor/xchunked_view.hpp"
14+
15+
namespace xt
16+
{
17+
TEST(xchunked_view, iterate)
18+
{
19+
std::vector<std::size_t> shape = {3, 4};
20+
std::vector<std::size_t> chunk_shape = {1, 2};
21+
xarray<double> a(shape);
22+
std::size_t chunk_nb = 0;
23+
auto chunked_view = xchunked_view<xarray<double>>(a, chunk_shape);
24+
for (auto it = chunked_view.begin(); it != chunked_view.end(); it++)
25+
{
26+
chunk_nb++;
27+
}
28+
29+
std::size_t expected_chunk_nb = (shape[0] / chunk_shape[0]) * (shape[1] / chunk_shape[1]);
30+
31+
EXPECT_EQ(chunk_nb, expected_chunk_nb);
32+
}
33+
34+
TEST(xchunked_view, assign)
35+
{
36+
std::vector<std::size_t> shape = {3, 4};
37+
std::vector<std::size_t> chunk_shape = {1, 2};
38+
xarray<double> a(shape);
39+
std::vector<double> data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
40+
std::copy(data.cbegin(), data.cend(), a.begin());
41+
xarray<double> b(shape);
42+
43+
as_chunked(b, chunk_shape) = a;
44+
45+
EXPECT_EQ(a, b);
46+
}
47+
48+
TEST(xchunked_view, assign_chunked_array)
49+
{
50+
std::vector<std::size_t> shape = {10, 10, 10};
51+
std::vector<std::size_t> chunk_shape = {2, 3, 4};
52+
auto a = chunked_array<double>(shape, chunk_shape);
53+
xarray<double> b(shape);
54+
auto ref = arange(0, 1000).reshape(shape);
55+
56+
as_chunked(a, chunk_shape) = ref;
57+
as_chunked(b, chunk_shape) = a;
58+
59+
EXPECT_EQ(ref, a);
60+
EXPECT_EQ(ref, b);
61+
}
62+
}

0 commit comments

Comments
 (0)