วิธีการแปลงอาร์เรย์ numpy เป็น vector <int> & (อ้างอิง) ด้วย SWIG


10

เป้าหมายของฉัน:

สร้าง 3 numpy arrays ใน python (2 อันจะถูกเตรียมค่าเริ่มต้นด้วยค่าเฉพาะ) จากนั้นส่งทั้งสามตัวผ่าน swig ไปยังฟังก์ชัน c ++ เป็นเวกเตอร์ อ้างอิง (นี่คือเพื่อหลีกเลี่ยงการคัดลอกข้อมูลและประสิทธิภาพการสูญเสีย) เมื่ออยู่ในฟังก์ชัน c ++ ให้เพิ่ม 2 อาร์เรย์และใส่ผลรวมลงในอาร์เรย์ที่ 3

vec_ref.h

#include <vector>
#include <iostream>

void add_vec_ref(std::vector<int>& dst, std::vector<int>& src1, std::vector<int>& src2);

vec_ref.cpp

#include "vec_ref.h"
#include <cstring> // need for size_t
#include <cassert>

void add_vec_ref(std::vector<int>& dst, std::vector<int>& src1, std::vector<int>& src2) {
    std::cout << "inside add_vec_ref" << std::endl;
    assert(src1.size() == src2.size());
    dst.resize(src1.size());

    for (size_t i = 0; i < src1.size(); i++) {
        dst[i] = src1[i] + src2[i];
    }
}

vec_ref.i

%module vec_ref
%{
    #define SWIG_FILE_WITH_INIT
    #include "vec_ref.h"
%}

%include "numpy.i"
%init %{
import_array();
%}

%include "std_vector.i"
%template(vecInt) std::vector<int>;
// %template(vecIntRef) std::vector<int> &; 

// %apply (std::vector<int> * INPLACE_ARRAY1, int DIM1) {(std::vector<int> * dst, int a),(std::vector<int> * src1, int b),(std::vector<int> * src2, int c)};
// %apply (std::vector<int> * INPLACE_ARRAY1) {(std::vector<int> * dst),(std::vector<int> * src1),(std::vector<int> * src2)};
// %apply (std::vector<int> & INPLACE_ARRAY1) {(std::vector<int> & dst),(std::vector<int> & src1),(std::vector<int> & src2)};
// %apply (std::vector<int> & INPLACE_ARRAY1, int DIM1) {(std::vector<int> & dst, int a),(std::vector<int> & src1, int b),(std::vector<int> & src2, int c)};

%include "vec_ref.h"

Makefile

all:
    rm -f *.so *.o *_wrap.* *.pyc *.gch vec_ref.py
    swig -c++ -python vec_ref.i
    g++ -O0 -g3 -fpic -c vec_ref_wrap.cxx vec_ref.h vec_ref.cpp -I/home/lmckeereid/tools/anaconda3/pkgs/python-3.7.3-h0371630_0/include/python3.7m/
    g++ -O0 -g3 -shared vec_ref_wrap.o vec_ref.o -o _vec_ref.so

tester.py

import vec_ref as vec
import numpy as np

a = np.array([1,2,3], dtype=np.intc)
b = np.array([4,5,6], dtype=np.intc)
c = np.zeros(len(a), dtype=np.intc)

print('---Before---\na:', a)
print('b:', b)
print('c:', c)

vec.add_vec_ref(c,a,b)

print('---After---\na:', a)
print('b:', b)
print('c:', c)

เอาท์พุท:

---Before---
a: [1 2 3]
b: [4 5 6]
c: [0 0 0]
Traceback (most recent call last):
  File "tester.py", line 12, in <module>
    vec.add_vec_ref(c,a,b)
TypeError: in method 'add_vec_ref', argument 1 of type 'std::vector< int,std::allocator< int > > &'

ฉันได้ลองใช้ความคิดเห็นทั้งหมดที่มีการใส่ความคิดเห็น% และคำสั่งเทมเพลต% ที่พบใน vec_ref.i แต่มันไม่ได้ผล

มี typemaps ที่ฉันควรจะรวมถึงที่ฉันไม่ได้?


3
มันเป็นไปไม่ได้. ใน C ++ คุณสามารถสร้างการอ้างอิงไปยังวัตถุที่มีอยู่จริงเท่านั้น อย่างไรก็ตามอาร์เรย์ numpy std::vectorไม่ได้มี
pschill

ที่เกี่ยวข้อง: stackoverflow.com/questions/51466189/…
Gabriel Devillers

คำตอบ:


3

ฉันเห็นด้วยกับ @pschill: ไม่สามารถรับ std :: vector ได้โดยไม่ต้องคัดลอกข้อมูล

อีกทางเลือกหนึ่งคือการใช้std::spanเทมเพลตคลาส (แนะนำใน C ++ 20) หรือspanเทมเพลตคลาสที่คล้ายกันที่กำหนดไว้ในไลบรารี

การสร้างstd::span<int>จะให้มุมมองของข้อมูลที่มีอยู่ในnumpyอาร์เรย์และให้ฟังก์ชั่นสมาชิกหลายสะดวก (เช่นoperator[], iterators, front(), back()ฯลฯ ) ใน C ++

การสร้างช่วงจะไม่คัดลอกข้อมูลจากอาร์เรย์ numpy


ขอบคุณที่ให้สิ่งที่ฉันเห็นว่าเป็นทางเลือกที่ดีที่สุด (นอกเหนือจากการสร้างชั้นเรียนของฉันเอง)
พิศวงงงงวย

ถ้าฉันต้องการใช้ (และปรับเปลี่ยน) std :: vector ในฟังก์ชัน C ++ ของฉันโดยไม่ต้องคัดลอกฉันจะมีทางเลือกอะไรบ้าง ตัวชี้ Raw เป็น std :: vector? shared_ptr to std :: vector?
Gabriel Devillers

@GabrielDevillers หากฉันเข้าใจคำถามของคุณหากมีเวกเตอร์อยู่และคุณต้องการแก้ไขในหน้าที่ของคุณฉันขอแนะนำให้ใช้การอ้างอิงถึงเวกเตอร์: std::vector<T>& v
NicholasM

@NicholasM ฉันหมายถึงใน API ที่ฉันต้องการห่อด้วยการใช้ SWIG ฉันถามเพราะฉันเข้าใจว่า SWIG ไม่สามารถห่อการอ้างอิงเวกเตอร์ที่ไม่ใช่ค่าอ้างอิงได้
Gabriel Devillers

โอ้ขอโทษ. ฉันขอแนะนำให้คุณสร้างคำถามใหม่ที่เน้นเฉพาะกรณีของคุณ
NicholasM

0

คุณสามารถอ้างถึงห้องสมุด Facebook faiss ซึ่งประสบความสำเร็จในสิ่งที่คุณต้องการเพื่อให้ได้มาซึ่งความงดงามยิ่งขึ้นโดย:

เฉพาะงูหลาม: numpy array <-> อินเตอร์เฟสตัวชี้ C ++ (เวกเตอร์)

คุณสามารถดูรหัสบนของหน้า Github

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.