파이썬은 C / C를 사용하여 모듈 호출을하는 ctypes ++

N 함유하는 노드에서, m도 특정 규칙 통신에 따른 샘플링 에지 :도 최근의 실험으로도 샘플링을 포함하는 연관된 컨볼 루션을 수행, 처리는 추상화 될 수있다. FB15k-237 데이터 세트를 사용하여 실험하기 때문에, 노드가 포함 14,541 샘플 면당 272,115, 30,000, 샘플 깊이 학습 실험 용납되는 8S을 필요 가장자리는 긴 GPU로 이어질 무료. 최종 효과는이 기록이 그렇게 최적화뿐만 아니라 학습 파이썬 호출 C 코드에 있지 않지만, C / C ++ 최적화 코드를 사용하려고 시작 나는 그래서.

파이썬 소스 코드

 def get_adj_and_degrees(num_nodes, triplets):
    """ Get adjacency list and degrees of the graph"""
    adj_list = [[] for _ in range(num_nodes)]
    for i, triplet in enumerate(triplets):
        adj_list[triplet[0]].append([i, triplet[2]])
        adj_list[triplet[2]].append([i, triplet[0]])

    degrees = np.array([len(a) for a in adj_list])
    adj_list = [np.array(a) for a in adj_list]
    return adj_list, degrees

여기에 get_adj_and_degrees기능 예를 들어, 우리는 기능을 최적화는 C / C ++를 사용합니다. 이 기능은 단순히 프리젠 테이션의 역할, 구체적인 내용은 중요하지 않습니다.

C / C ++ 구현 코드

우리는 sampler.hpp다음과 같이 기능, 파일의 정의는 최적화 :

#ifndef SAMPLER_H
#define SAMPLER_H

#include <vector>
#include "utility.hpp"

using namespace std;

// global graph data
int num_node = 0;
int num_edge = 0;
vector<int> degrees; // shape=[N]
vector<vector<vector<int>>> adj_list; // shape=[N, variable_size, 2]


void build_graph(int* src, int* rel, int* dst, int num_node_m, int num_edge_m) {
    num_node = num_node_m;
    num_edge = num_edge_m;

    // resize the vectors
    degrees.resize(num_node);
    adj_list.resize(num_node);

    for (int i = 0; i < num_edge; i++) {
        int s = src[i];
        int r = rel[i];
        int d = dst[i];

        vector<int> p = {i, d};
        vector<int> q = {i, s};
        adj_list[s].push_back(p);
        adj_list[d].push_back(q);
    }

    for (int i = 0; i < num_node; i++) {
        degrees[i] = adj_list[i].size();
    }
}

#endif

글로벌 변수 후에 사용하는 공정이므로 여기서 결과의 C / C ++ 함수가 저장된다. 우리의 초점은 파이썬을 호출하는 방법에 있기 때문에 함수의 구체적인 내용은 이야기하지 않습니다.

그래서 라이브러리 생성

우리는 C 함수와 C ++ 함수를 도출 할 필요가 있도록하는 ctypes 만 C 함수를 호출 할 수 있습니다. 우리는 그래서 lib.cpp다음과 같은 정의를합니다

#ifndef LIB_H
#define LIB_H

#include "sampler.hpp"

extern "C" {
    void build_graph_c(int* src, int* rel, int* dst, int num_node, int num_edge) {
        build_graph(src, rel, dst, num_node, num_edge);
    }
}

#endif

그런 다음 코드를 추가 최적화하기 위해, 컴파일에 다음 명령을 사용하여 O3, march=native옵션 :

g++ lib.cpp -fPIC -shared -o libsampler.so -O3 -march=native

파이썬은 C / C ++ 함수를 호출

컴파일 후, 현재 디렉토리 아래에 생성 libsampler.so라이브러리, 우리는 파이썬 코드를 다음과 같이 구성되어의 C / C ++ 함수를 호출하는 파이썬 코드를 작성할 수 있습니다 :

import numpy as np
import time
from ctypes import cdll, POINTER, Array, cast
from ctypes import c_int


class CPPLib:
    """Class for operating CPP library

    Attributes:
        lib_path: (str) the path of a library, e.g. 'lib.so.6'
    """
    def __init__(self, lib_path):
        self.lib = cdll.LoadLibrary(lib_path)

        IntArray = IntArrayType()
        self.lib.build_graph_c.argtypes = (IntArray, IntArray, IntArray, c_int, c_int)
        self.lib.build_graph_c.restype = None

    def build_graph(self, src, rel, dst, num_node, num_edge):
        self.lib.build_graph_c(src, rel, dst, num_node, num_edge)

class IntArrayType:
    # Define a special type for the 'int *' argument
    def from_param(self, param):
        typename = type(param).__name__
        if hasattr(self, 'from_' + typename):
            return getattr(self, 'from_' + typename)(param)
        elif isinstance(param, Array):
            return param
        else:
            raise TypeError("Can't convert %s" % typename)

    # Cast from array.array objects
    def from_array(self, param):
        if param.typecode != 'i':
            raise TypeError('must be an array of doubles')
        ptr, _ = param.buffer_info()
        return cast(ptr, POINTER(c_int))

    # Cast from lists/tuples
    def from_list(self, param):
        val = ((c_int) * len(param))(*param)
        return val

    from_tuple = from_list

    # Cast from a numpy array
    def from_ndarray(self, param):
        return param.ctypes.data_as(POINTER(c_int))

개요

파이썬 자체가 어려운 일이 아니다는 C / C ++ 기능을 사용하여 라이브러리 호출을하는 ctypes하지만 NumPy와 특히 최적화 할 때 최적화 된 코드는 과학 연산 라이브러리로, 참으로 구덩이입니다. 이 라이브러리 자체는 크게 C ++로 구현 자신의 단어를 사용하여 최적화 되었기 때문에, 그것은 또한 가능성이 최적화 이전보다 악화 될 것입니다.

추천

출처www.cnblogs.com/weilonghu/p/12122063.html