세상의 변화에 대해 관심이 많은 이들의 Tech Blog search

파이썬 numba 모듈 설명

|

목차

1. Introduction

파이썬을 사용하다 보면 편리한 기능에 감탄하는 경우가 많지만 종종 속도에 대한 아쉬움을 느낄 때가 있다. 특히 머신러닝과 관련된 작업들을 하다 보면, 데이터 처리를 하는 과정에 있어서 좀 더 빠른 진행을 요구하는 경우가 많은데, 이를 위한 모듈 중 하나가 Numba이다.

공식문서를 확인해보면 아래와 같은 설명을 찾을 수 있다.

Numba makes Python code fast.
Numba is an open source JIT compiler that translates a subset of Python and NumPy code into fast machine code.

해석하면, 파이썬과 넘파이 코드를 빠르게 실행시켜주는 JIT 컴파일러라고 할 수 있겠다.

Numba의 작동원리는 다음과 같다.

  • 데커레이팅된 함수에 대한 파이썬 bytecode를 일ㄹ고 이를 함수의 입력 인수 유형에 대한 정보와 결합한다.
  • 코드를 분석하고 최적화한 후, LLVM compiler library를 사용하여 함수의 machine code 버전을 반들고, 이를 사용자의 CPU 능력에 맞춘다.
  • 이 compiled된 버전이 앞으로 그 함수를 호출할 때마다 사용된다.

Numba를 사용하기 위해서 새로운 언어를 배운다거나 할 필요는 전혀 없다. 역시 공식문서에서는 아래와 같이 밝히고 있다.

You don’t need to replace the Python interpreter, run a separate compilation step, or even have a C/C++ compiler installed.
Just apply one of the Numba decorators to your Python function, and Numba does the rest.

Numba 모듈이 모든 파이썬 코드를 최적화해주는 것은 아니다. 일부 파이썬 코드와 Numpy에 대해서만 작동하며 대다수의 다른 모듈을 이용한 코드를 최적화 시켜주지는 못한다. 예를 들어 Numba은 Pandas를 이해하지 못한다. 그럼에도 특정 목적에 따라 충분히 활용할 수 있는 가치가 있는 모듈이라고 할 수 있겠다.


2. 기본적인 사용법

2.1. 예시

예시를 살펴보면서 Numba의 효과를 확인해보도록 하겠다.

from time import perf_counter
from numba import jit

# 일반적인 loop
def pure_sum(n):
    result = 0
    for i in range(0, n+1):
        result += i
    return result

# Numba 모듈 사용
@jit(nopython=True, cache=True)
def numba_sum(n):
    result = 0
    for i in range(0, n+1):
        result += i
    return result

# 시간 재기: 일반
start = perf_counter()
pure_sum(100000000)
print(perf_counter() - start)

# 시간 재기에 앞서 먼저 Compile을 해준다.
numba_sum(1)

# 시간 재기: Numba
start = perf_counter()
numba_sum(100000000)
print(perf_counter() - start)

결과는 아래와 같다.

6.040823099999898      # 일반
4.590000003190653e-05  # Numba

pure 파이썬 코드보다 훨씬 빠르다는 것을 확인할 수 있다.

2.2. @jit 데커레이터의 모드

@jit 데커레이터는 nopythonobject라는 2가지 compilation 모드로 작동한다. 위 예제에서 nopython=True를 통해 Numba에게 nopython 모드로 작동하라고 지시한 셈인데, 이 모드는 decorate된 function을 근본적으로 compile하여 Python Interpreter의 개입 없이 전체가 작동하도록 한다.

만약 nopython 모드가 잘 작동하지 않을 경우, Numba은 object 모드를 통해 compile 할 수 있다. @jit(nopython=True)가 아닌 @jit이라고만 데커레이팅하면 이 모드가 작동하게 된다. 본 모드에서는 Numba은 loop를 식별하여 machine code에서 compile하며 나머지는 Intereter code에서 compile하게 된다. 더 나은 성능을 기대한다면 이 모드가 아닌 nopython 모드를 사용해야 한다.

2.3. 다른 Compilation 옵션들

2.3.1. nogil

Numba가 파이썬 코드를 native type과 변수에서만 작동하는 native code로 최적화하고 싶을 때, 파이썬의 GIL(Global Interpreter Lock)을 유지하는 것은 불필요하다.

@jit(nogil=True) 옵션을 사용하면 Numba는 GIL을 해제할 것이다.

2.3.2. cache

파이썬 프로그램을 호출할 때, 컴파일 시간을 피하기 위해 function의 결과를 파일 기반 cache에 쓰도록 Numba에 지시할 수 있다. 이를 실행하기 위해서는 @jit(cache=True) 옵션을 사용하면 된다.

2.3.3. parallel

parallel semantics를 가진 function에 대해 자동화된 병렬화를 제공한다. 반드시 nopython=True 모드에서만 실행되어야 하며 @jit(nopython=True, parallel=True)를 통해 사용할 수 있다.


Reference

공식문서