【问题标题】:How to create array in C++ similar to Python's numpy array?如何在 C++ 中创建类似于 Python 的 numpy 数组的数组?
【发布时间】:2017-05-03 09:32:03
【问题描述】:

我正在转换Python program to C++ 格式。

Python 有一个如下格式的数组。

boxes = np.zeros((1, 300, 4, 5, 1), dtype = np.float)

创建与boxes 数组功能相似的C++ 数组的最佳方法是什么?

【问题讨论】:

  • 使用外部库。 Eigen 是一个选项,但还有其他选项。
  • 按照 DavidW 的说法,xtensor 是一个更像 numpy 的选项
  • 谢谢,我会研究这些库。
  • @batuman 请确认您愿意写x[0][185][3][4][0]
  • 关于结构:这里的结构将是您的 dtype。如果你只有双打,就不需要一个。

标签: python c++ c++11 numpy


【解决方案1】:

事实上,numpy 分配了一个连续的数组存储,strides 用于基于多维索引计算内存偏移量。要在 C++ 中实现类似的结果,您可以编写如下代码:

#include <vector>
#include <memory>
#include <cstddef>
#include <cstdio>

class NDArray {
    std::vector<size_t> m_dims, m_strides;
    std::unique_ptr<float[]> m_buf;

    public:
        NDArray(std::vector<size_t> dims):
            m_dims{std::move(dims)}
        {
            m_strides.resize(m_dims.size());
            size_t stride = 1;
            for (int i = m_dims.size() - 1; i >= 0; -- i) {
                m_strides[i] = stride;
                stride *= m_dims[i];
            }
            m_buf.reset(new float[stride]);
        }

        float& operator[] (std::initializer_list<size_t> idx) {
            size_t offset = 0;
            auto stride = m_strides.begin();
            for (auto i: idx) {
                offset += i * *stride;
                ++ stride;
            }
            return m_buf[offset];
        }
};

int main() {
    NDArray arr({2, 3});
    arr[{1, 2}] = 3;
    arr[{1, 1}] = 2;
    printf("%g\n", arr[{1, 2}]);
}

【讨论】:

  • 这种方式也可以映射或复制到 numpy 数组,因为接口 C++ 和 Python 的 API 将简单地返回一个指针。但随后将是原始指针而不是向量。如果任何 C++ 程序员对这个想法说“ew”,那么整个 Phyton\C++ API 都在原始指针上工作,没有办法绕过它。有 Boost-Python 替代方案,但速度较慢
【解决方案2】:

我猜是

auto boxes = std::array<
                std::array<
                   std::array<
                      std::array<
                         std::array<float, 1U>, 300U>, 4U>, 5U>, 1U> {};

或者,为了避免Humam Helfawi指出的堆栈溢出问题,您可以使用std::vector(所以堆内存)如下

   auto boxes2 = std::vector<
                    std::vector<
                       std::vector<
                          std::vector<
                             std::vector<float>>>>>
                                (1U, std::vector<
                                        std::vector<
                                           std::vector<
                                              std::vector<float>>>>
                                   (300U, std::vector<
                                             std::vector<
                                                std::vector<float>>>
                                      (4U, std::vector<
                                              std::vector<float>>
                                         (5U, std::vector<float>
                                             (1U, 0.0f)))));

或者,按照 n.caillou 的建议,

using boxA5 = std::array<
                 std::array<
                    std::array<
                       std::array<
                          std::array<float, 1U>, 300U>, 4U>, 5U>, 1U>;

auto boxes3 = std::unique_ptr<boxA5> { new boxA5{} };

【讨论】:

  • 我正在考虑创建一个具有 int a、float[] b、float[] c、float[] d、int e 的结构;
  • @HumamHelfawi - 谢谢;添加了std::vector 解决方案。
  • 还有明显的unique_ptr&lt;array&lt;array&lt;...;效率更高
  • @batuman - 抱歉;也许我不了解 pyton,但...据我所知,您询问了 1x300x5x4x1 浮点数的多维数组
  • @n.caillou - 这很明显,但我没有考虑过;谢谢
【解决方案3】:
#include <iostream>
#include <vector>  
vector<vector<vector<vector<double> > > > v;
    v.resize(1);
    v[0].resize(300);
    for(int i=0;i<300;i++)
    {
        v[0][i].resize(4);
        for(int j=0;j<4;j++)
        {
            v[0][i][j].resize(5);
            for(int l=0;l<5;l++)
                v[0][i][j][l]=double(0.0);
        }
    }

【讨论】:

  • #include #include
  • numpy 数组是连续数组,据我所知是静态的,而不是易失的向量树
猜你喜欢
  • 1970-01-01
  • 2022-06-15
  • 2018-04-18
  • 2020-11-24
  • 2017-08-15
  • 1970-01-01
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
相关资源
最近更新 更多