我试图理解为什么numpy的cumsum函数比手动c++循环要快得多。我正在使用pybind提供从C++代码到python的映射。
数字优先:

[nav] In [24]: x = np.arange(100_000, dtype=np.float32)

[nav] In [25]: %timeit np.cumsum(x)
295 µs ± 34.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

[ins] In [26]: %timeit derived.cumsum(x)
9.26 ms ± 137 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
现在如何获得derived.cumsum(x)
template <typename Sequence,
          typename = std::enable_if_t<std::is_rvalue_reference_v<Sequence&&>>>
inline py::array_t<typename Sequence::value_type> as_pyarray(Sequence&& seq) {
  auto size = seq.size();
  auto data = seq.data();
  auto seq_ptr = std::make_unique<Sequence>(std::move(seq));
  auto capsule = py::capsule(seq_ptr.get(), [](void* p) {
    std::unique_ptr<Sequence>(reinterpret_cast<Sequence*>(p));
  });
  seq_ptr.release();
  return py::array(size, data, capsule);
}

std::vector<float> cumsum(const std::vector<float>& nums) {
  std::vector<float> result(nums.size());
  float sum = 0;
  for (size_t i = 0; i < nums.size(); ++i) {
    sum += nums[i];
    result[i] = sum;
  }
  return result;
}

PYBIND11_MODULE(derived, m) {
  m.def("cumsum", [](const std::vector<float>& nums) {
    auto result = cumsum(nums);
    return as_pyarray(std::move(result));
  });
}
as_pyarray是从this pybind问题获得的,该问题可确保在python和c++之间进行交互时零复制。
请注意,C++代码是使用-O3 -DNDEBUG -fPIC编译的。

最佳答案

问题在于cumsum。 const std::vector<float>&仍在进行相当昂贵的复制。直接将py::array_t<float>作为参数可以解决此问题。
有关更多详细信息,请访问:https://github.com/pybind/pybind11/issues/1042

10-06 01:55