파이썬의 속도를 개선할 수 있는 방법중 하나인 ctypes에 대해 알아보자.
ctypes는 C로 작성한 .so(mac, linux)나 .dll(windows)를 이용할 수 있도록 해주는 라이브러리이다.
그리고 이렇게 C로 작성해서 코드를 돌리면 당연히 파이썬보다 빠르니까 지금 당장 속도가 아쉬운 상황이라면 부하가 많이 걸리는 함수를 C로 빼내서 작성하는 식으로 최적화를 할 수 있다.
상세한 설명은 정보의 바다에 많으니까 거기서 찾도록 하고, 이 글을 읽는 당신과 쓰는 나 모두 시간이 없으므로 최대한 빨리 사용법에 대해서만 알아보자.
갈 땐 가더라도 알 건 알고 가자
.so나 .dll파일 내부가 어떻게 되어있는지 파이썬 입장에서는 알 수 없으므로, 래퍼를 이용해 추상화를 한 후에 사용하면 편하다.좌표값들의 배열을 받아온 후 일정 거리 내의 좌표값들만 추려서 돌려주는 예제이다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long long* worker(long long* works, int work_length, int criteria) {
long long* ret = (long long*)malloc(sizeof(long long) * work_length * 2);
memset(ret, -1, sizeof(long long) * work_length * 2);
long long ri = 0;
for (int i = 0; i < work_length * 2; i += 2) {
long long x = works[i];
long long y = works[i + 1];
// printf("%lld, %lld\n", x, y);
if (x * x + y * y <= 1ll* criteria * criteria) {
ret[ri] = x;
ret[ri + 1] = y;
ri += 2;
}
}
return ret;
}
#ifdef _WIN32
__declspec(dllexport)long long* worker(long long* works, int work_length, int criteria);
#endif
import ctypes
import os
import numpy as np
lib = ctypes.CDLL("./clib.so" if os.name == "posix" else "./clib.dll")
f = lib.worker
f.restype = ctypes.POINTER(ctypes.c_longlong)
def _clib(nparr: np.ndarray):
length = len(nparr)
nparr = nparr.astype("int64")
ret_raw = f(np.ctypeslib.as_ctypes(nparr), length, 5)
ret = np.ctypeslib.as_array(ret_raw, shape=[length, 2])
return ret[ret[:, 0] != -1]
gcc clib.c -o clib.so -sharedgcc clib.c -o clib.dll -sharedlonglong형식의 포인터라고 지정해주었다. (ctypes.c_longlong)dtype)을 제대로 맞춰주어야 한다. 예제에선 int64로 맞춰주었다.dtype를 잘 맞춰서 np.array를 생성하자.