Skip to content

Commit f1ef4c5

Browse files
committed
compilation issues fix
1 parent d76ac16 commit f1ef4c5

File tree

6 files changed

+83
-25
lines changed

6 files changed

+83
-25
lines changed

benchmark/benchmark_pytensor.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from xtensor_python_benchmark import sum_tensor
2+
import numpy as np
3+
4+
u = np.ones(1000000, dtype=float)
5+
#print(sum_tensor(u))
6+
from timeit import timeit
7+
print (timeit ('sum_tensor(u)', setup='from __main__ import u, sum_tensor', number=1000))

benchmark/main.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
#include "pybind11/pybind11.h"
22
#include "pybind11/numpy.h"
3+
#include "numpy/arrayobject.h"
34
#include "xtensor/xtensor.hpp"
45
#include "xtensor/xarray.hpp"
56
#include "xtensor-python/pyarray.hpp"
7+
#include "xtensor-python/pytensor.hpp"
68

79
#include <complex>
810

911
namespace py = pybind11;
1012

1113
PYBIND11_PLUGIN(xtensor_python_benchmark)
1214
{
15+
if(_import_array() < 0)
16+
{
17+
PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import");
18+
return nullptr;
19+
}
20+
1321
py::module m("xtensor_python_benchmark", "Benchmark module for xtensor python bindings");
1422

1523
m.def("sum_array", [](xt::pyarray<double> const& x) {
@@ -20,6 +28,14 @@ PYBIND11_PLUGIN(xtensor_python_benchmark)
2028
}
2129
);
2230

31+
m.def("sum_tensor", [](xt::pytensor<double, 1> const& x) {
32+
double sum = 0;
33+
for(auto e : x)
34+
sum += e;
35+
return sum;
36+
}
37+
);
38+
2339
m.def("pybind_sum_array", [](py::array_t<double> const& x) {
2440
double sum = 0;
2541
size_t size = x.size();

include/xtensor-python/pybuffer_adaptor.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace xt
3131
using iterator = pointer;
3232
using const_iterator = const_pointer;
3333

34+
pybuffer_adaptor() = default;
3435
pybuffer_adaptor(pointer data, size_type size);
3536

3637
bool empty() const noexcept;
@@ -70,13 +71,13 @@ namespace xt
7071
}
7172

7273
template <class T>
73-
inline bool pybuffer_adapgtor<T>::empty() const noexcept
74+
inline bool pybuffer_adaptor<T>::empty() const noexcept
7475
{
7576
return m_size == 0;
7677
}
7778

7879
template <class T>
79-
inline auto pybuffer_adaptor<T>::size() const noexcept
80+
inline auto pybuffer_adaptor<T>::size() const noexcept -> size_type
8081
{
8182
return m_size;
8283
}
@@ -88,7 +89,7 @@ namespace xt
8889
}
8990

9091
template <class T>
91-
inline auto pybuffer_adaptor<T>::operator[](size_type i) -> const_reference
92+
inline auto pybuffer_adaptor<T>::operator[](size_type i) const -> const_reference
9293
{
9394
return p_data[i];
9495
}

include/xtensor-python/pycontainer.hpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
#include <functional>
1313
#include <numeric>
14+
#include <cmath>
1415
#include "pybind11/pybind11.h"
16+
#include "pybind11/common.h"
1517
#include "xtensor/xtensor_forward.hpp"
1618
#include "xtensor/xiterator.hpp"
1719

@@ -54,7 +56,7 @@ namespace xt
5456

5557
const shape_type& shape() const;
5658
const strides_type& strides() const;
57-
const backtrides_type& backstrides() const;
59+
const backstrides_type& backstrides() const;
5860

5961
template <class... Args>
6062
reference operator()(Args... args);
@@ -141,7 +143,7 @@ namespace xt
141143
template <size_t dim = 0>
142144
size_type data_offset(const strides_type&) const;
143145

144-
template <size_type dim, class... Args>
146+
template <size_t dim, class... Args>
145147
size_type data_offset(const strides_type& strides, size_type i, Args... args) const;
146148

147149
template <class It>
@@ -150,6 +152,22 @@ namespace xt
150152

151153
namespace detail
152154
{
155+
// TODO : switch on pybind11::is_fmt_numeric when it is available
156+
template <typename T, typename SFINAE = void>
157+
struct is_fmt_numeric
158+
{
159+
static constexpr bool value = false;
160+
};
161+
162+
template <typename T>
163+
struct is_fmt_numeric<T, std::enable_if_t<std::is_arithmetic<T>::value>>
164+
{
165+
static constexpr bool value = true;
166+
static constexpr int index = std::is_same<T, bool>::value ? 0 : 1 + (
167+
std::is_integral<T>::value ? std::log2(sizeof(T)) * 2 + std::is_unsigned<T>::value : 8 + (
168+
std::is_same<T, double>::value ? 1 : std::is_same<T, long double>::value ? 2 : 0));
169+
};
170+
153171
template <class T>
154172
struct numpy_traits
155173
{
@@ -167,7 +185,7 @@ namespace xt
167185

168186
using value_type = std::remove_const_t<T>;
169187

170-
static constexpr int type_num = value_list[pybind11::detail::is_fmt_numeric<value_type>::index];
188+
static constexpr int type_num = value_list[is_fmt_numeric<value_type>::index];
171189
};
172190
}
173191

@@ -244,7 +262,7 @@ namespace xt
244262
}
245263

246264
template <class D>
247-
inline auto pycontianer<D>::backstrides() const -> const backstrides_type&
265+
inline auto pycontainer<D>::backstrides() const -> const backstrides_type&
248266
{
249267
return static_cast<const derived_type*>(this)->backstrides_impl();
250268
}
@@ -298,7 +316,7 @@ namespace xt
298316
}
299317

300318
template <class D>
301-
inline auto pycontainer<D>:data() const -> const container_type&
319+
inline auto pycontainer<D>::data() const -> const container_type&
302320
{
303321
return static_cast<const derived_type*>(this)->data_impl();
304322
}

include/xtensor-python/pytensor.hpp

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace pybind11
2929
namespace detail
3030
{
3131
template <class T, std::size_t N>
32-
struct handle_type_name<pytensor<T, std::size_t N>>
32+
struct handle_type_name<xt::pytensor<T, N>>
3333
{
3434
static PYBIND11_DESCR name()
3535
{
@@ -38,9 +38,9 @@ namespace pybind11
3838
};
3939

4040
template <class T, std::size_t N>
41-
struct pyobject_caster<pytensor<T, N>>
41+
struct pyobject_caster<xt::pytensor<T, N>>
4242
{
43-
using type = pytensor<T, N>;
43+
using type = xt::pytensor<T, N>;
4444

4545
bool load(handle src, bool)
4646
{
@@ -50,7 +50,7 @@ namespace pybind11
5050

5151
static handle cast(const handle& src, return_value_policy, handle)
5252
{
53-
src.inc_ref();
53+
return src.inc_ref();
5454
}
5555

5656
PYBIND11_TYPE_CASTER(type, handle_type_name<type>::name());
@@ -82,12 +82,17 @@ namespace xt
8282
using semantic_base = xcontainer_semantic<self_type>;
8383
using base_type = pycontainer<pytensor<T, N>>;
8484
using container_type = typename base_type::container_type;
85+
using pointer = typename base_type::pointer;
86+
using size_type = typename base_type::size_type;
87+
using shape_type = typename base_type::shape_type;
88+
using strides_type = typename base_type::strides_type;
89+
using backstrides_type = typename base_type::backstrides_type;
8590

8691
pytensor();
8792

8893
pytensor(pybind11::handle h, borrowed_t);
8994
pytensor(pybind11::handle h, stolen_t);
90-
pyarray(const pybind11::object &o);
95+
pytensor(const pybind11::object &o);
9196

9297
pytensor(const shape_type& shape, const strides_type& strides);
9398
explicit pytensor(const shape_type& shape);
@@ -101,6 +106,9 @@ namespace xt
101106
void reshape(const shape_type& shape);
102107
void reshape(const shape_type& shape, const strides_type& strides);
103108

109+
using base_type::begin;
110+
using base_type::end;
111+
104112
static self_type ensure(pybind11::handle h);
105113
static bool check_(pybind11::handle h);
106114

@@ -132,10 +140,6 @@ namespace xt
132140
template <class T, std::size_t N>
133141
inline pytensor<T, N>::pytensor()
134142
{
135-
std::fill(m_shape.begin(), m_shape.end(), T(0));
136-
std::fill(m_strides.begin(), m_strides.end(), T(0));
137-
std::fill(m_backstrides.begin(), m_backstrides.end(), T(0));
138-
m_data = container_type(nullptr, 0);
139143
}
140144

141145
template <class T, std::size_t N>
@@ -156,20 +160,24 @@ namespace xt
156160
inline pytensor<T, N>::pytensor(const pybind11::object& o)
157161
: pybind11::object(base_type::raw_array_t(o.ptr()), stolen)
158162
{
163+
//std::cout << "Object constructor" << std::endl;
159164
if(!this->m_ptr)
160165
throw pybind11::error_already_set();
166+
init_from_python();
161167
}
162168

163169
template <class T, std::size_t N>
164170
inline pytensor<T, N>::pytensor(const shape_type& shape,
165171
const strides_type& strides)
166172
{
173+
//std::cout << "Shape + strides constructor" << std::endl;
167174
init_tensor(shape, strides);
168175
}
169176

170177
template <class T, std::size_t N>
171178
inline pytensor<T, N>::pytensor(const shape_type& shape)
172179
{
180+
//std::cout << "Shape constructor" << std::endl;
173181
base_type::fill_default_strides(shape, m_strides);
174182
init_tensor(shape, m_strides);
175183
}
@@ -178,6 +186,7 @@ namespace xt
178186
template <class E>
179187
inline pytensor<T, N>::pytensor(const xexpression<E>& e)
180188
{
189+
//std::cout << "Extended constructor" << std::endl;
181190
semantic_base::assign(e);
182191
}
183192

@@ -189,8 +198,9 @@ namespace xt
189198
}
190199

191200
template <class T, std::size_t N>
192-
inline void reshape(const shape_type& shape)
201+
inline void pytensor<T, N>::reshape(const shape_type& shape)
193202
{
203+
//std::cout << "Reshape(shape)" << std::endl;
194204
if(shape != m_shape)
195205
{
196206
strides_type strides;
@@ -200,17 +210,20 @@ namespace xt
200210
}
201211

202212
template <class T, std::size_t N>
203-
inline void reshape(const shape_type& shape, const strides_type& strides)
213+
inline void pytensor<T, N>::reshape(const shape_type& shape, const strides_type& strides)
204214
{
215+
//std::cout << "Reshape(shape, strides)" << std::endl;
205216
self_type tmp(shape, strides);
206217
*this = std::move(tmp);
207218
}
208219

209220
template <class T, std::size_t N>
210221
inline auto pytensor<T, N>::ensure(pybind11::handle h) -> self_type
211222
{
223+
//std::cout << "Ensure" << std::endl;
212224
auto result = pybind11::reinterpret_steal<self_type>(base_type::raw_array_t(h.ptr()));
213-
if(!result)
225+
//auto result = pybind11::reinterpret_steal<self_type>(h.ptr());
226+
if(result.ptr() == nullptr)
214227
PyErr_Clear();
215228
return result;
216229
}
@@ -219,12 +232,13 @@ namespace xt
219232
inline bool pytensor<T, N>::check_(pybind11::handle h)
220233
{
221234
int type_num = detail::numpy_traits<T>::type_num;
222-
return PyArray_Check(h.ptr()) && PyArray_EquivTypenums(PyArray_Type(h.ptr()), type_num);
235+
return PyArray_Check(h.ptr()) && PyArray_EquivTypenums(PyArray_TYPE(h.ptr()), type_num);
223236
}
224237

225238
template <class T, std::size_t N>
226239
inline void pytensor<T, N>::init_tensor(const shape_type& shape, const strides_type& strides)
227240
{
241+
//std::cout << "init tensor" << std::endl;
228242
npy_intp python_strides[N];
229243
std::transform(strides.beign(), strides.end(), python_strides,
230244
[](auto v) { return sizeof(T) * v; });
@@ -252,22 +266,24 @@ namespace xt
252266
template <class T, std::size_t N>
253267
inline void pytensor<T, N>::init_from_python()
254268
{
269+
//std::cout << "init from python" << std::endl;
255270
if(PyArray_NDIM(this->m_ptr) != N)
256271
throw std::runtime_error("NumPy: ndarray has incorrect number of dimensions");
257272

258273
std::copy(PyArray_DIMS(this->m_ptr), PyArray_DIMS(this->m_ptr) + N, m_shape.begin());
259274
std::transform(PyArray_STRIDES(this->m_ptr), PyArray_STRIDES(this->m_ptr) + N, m_strides.begin(),
260275
[](auto v) { return v / sizeof(T); });
261276
adapt_strides();
262-
m_data = container_type(PyArray_DATA(this->m_ptr), PyArray_SIZE(this->m_ptr));
277+
m_data = container_type(reinterpret_cast<pointer>(PyArray_DATA(this->m_ptr)),
278+
static_cast<size_type>(PyArray_SIZE(this->m_ptr)));
263279
}
264280

265281
template <class T, std::size_t N>
266282
inline void pytensor<T, N>::adapt_strides()
267283
{
268284
for(size_type i = 0; i < m_shape.size(); ++i)
269285
{
270-
if(m_shape_[i] == 1)
286+
if(m_shape[i] == 1)
271287
{
272288
m_strides[i] = 0;
273289
m_backstrides[i] = 0;
@@ -298,13 +314,13 @@ namespace xt
298314
}
299315

300316
template <class T, std::size_t N>
301-
inline auto pytensor<T, N>::data() -> container_type&
317+
inline auto pytensor<T, N>::data_impl() -> container_type&
302318
{
303319
return m_data;
304320
}
305321

306322
template <class T, std::size_t N>
307-
inline auto pytensor<T, N>::data() const -> const container_type&
323+
inline auto pytensor<T, N>::data_impl() const -> const container_type&
308324
{
309325
return m_data;
310326
}

0 commit comments

Comments
 (0)