๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Langauge/Python

[Python] ์—ฐ์‚ฐ ์†๋„ ์˜ฌ๋ฆฌ๊ธฐ - Numba

728x90
๋ฐ˜์‘ํ˜•
๐Ÿ ๋ณธ ๊ฒŒ์‹œ๊ธ€์€ Python 3.11.0 ํ™˜๊ฒฝ์—์„œ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!

 

Numba๋Š” Python์„ ์œ„ํ•œ Just-In-Time(JIT) ์ปดํŒŒ์ผ๋Ÿฌ๋กœ, ์ฃผ๋กœ ์ˆ˜์น˜ ๊ณ„์‚ฐ ๋ฐ ๊ณผํ•™์  ์ปดํ“จํŒ…์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

Numpy์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋  ๋•Œ ํŠนํžˆ ๊ฐ•๋ ฅํ•˜๋‹ค.

 

ํŠน์ง•

  • JIT ์ปดํŒŒ์ผ : ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ ์‹œ๊ฐ„์— ์ปดํŒŒ์ผ ํ•˜์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒํ•œ๋‹ค.
  • Numpy ํ˜ธํ™˜ : Numpy ๋ฐฐ์—ด๊ณผ ๋งŽ์€ ํ•จ์ˆ˜์™€ ์—ฐ์‚ฐ์„ ์ง€์›ํ•œ๋‹ค.
  • GPU ์ง€์› : NVIDIA GPU์—์„œ CUDA๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ์ง€์›ํ•œ๋‹ค.
  • ๊ฐ„ํŽธํ•œ ์‚ฌ์šฉ : ๊ธฐ์กด Python ์ฝ”๋“œ์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์žฅ์ 

  • ์„ฑ๋Šฅ ํ–ฅ์ƒ : Python ์ฝ”๋“œ๋ฅผ C, Fortran๊ณผ ์œ ์‚ฌํ•œ ์†๋„๋กœ ์‹คํ–‰ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.
  • ์ง๊ด€์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค : ์ฝ”๋“œ๋ฅผ ์ตœ์†Œํ•œ์˜ ์ˆ˜์ •์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด, ํ•™์Šต ๊ณก์„ ์ด ๋‚ฎ๋‹ค.
  • ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ : JIT ์ปดํŒŒ์ผ ์™ธ์—๋„, ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ, GPU ๊ฐ€์†, ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž… ์ง€์› ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

 

 

GitHub - numba/numba: NumPy aware dynamic Python compiler using LLVM

NumPy aware dynamic Python compiler using LLVM. Contribute to numba/numba development by creating an account on GitHub.

github.com

 

pip install numba

 

import numpy as np
from numba import njit
import time

def sum_array1(arr):
    total = 0.0
    for i in range(arr.size):
        total += arr[i]
    return total

@njit
def sum_array2(arr):
    total = 0.0
    for i in range(arr.size):
        total += arr[i]
    return total

# NumPy ๋ฐฐ์—ด ์ƒ์„ฑ
data = np.arange(1, 100000001)

# Numba๋ฅผ ์‚ฌ์šฉํ•œ ํ•จ์ˆ˜ ํ˜ธ์ถœ
start = time.time()
result = sum_array1(data)
print(f"No JIT:{time.time() - start:.3f}sec")
start = time.time()
result = sum_array2(data)
print(f"JIT:{time.time() - start:.3f}sec")

๋Œ€์šฉ๋Ÿ‰ ์—ฐ์‚ฐ์˜ ๊ฒฝ์šฐ JIT๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ™•์‹คํ•˜๊ฒŒ ๋น ๋ฅด์ง€๋งŒ, ์˜คํžˆ๋ ค ์ž‘์€ ์—ฐ์‚ฐ์˜ ๊ฒฝ์šฐ ์ดˆ๊ธฐ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ์žˆ์œผ๋ฏ€๋กœ ํ˜ธํžˆ๋ ค ์„ฑ๋Šฅ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  Numba๋Š” ๋ชจ๋“  Python lib๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค. (OpenCV ์ง€์›ํ•˜์ง€ ์•Š์Œ...)

 

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ

@njit

  • Numba์˜ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์ปดํŒŒ์ผ๋Ÿฌ
from numba import njit

@njit
def my_function(x):
    return x + 1

 

@jit

  • @njit์™€ ๋™์ผํ•˜๋‚˜, ์ปดํŒŒ์ผ ์˜ต์…˜์„ ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์ž๋ฅผ ๊ฐ€์ง„๋‹ค. no_python=True๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ Python ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋„๋ก ๊ฐ•์ œํ•œ๋‹ค.
from numba import jit

@jit(nopython=True)
def my_function(x):
    return x + 1

 

@cuda.jit

  • CUDA GPU์—์„œ ์‹คํ–‰ ํ•  ์ˆ˜ ์žˆ๋Š” ์ปค๋„ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. GPU ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค.
from numba import cuda

@cuda.jit
def gpu_function(a, b, c):
    idx = cuda.grid(1)
    if idx < c.size:
        c[idx] = a[idx] + b[idx

 

@guvectorize

  • ๋ฒกํ„ฐํ™”๋œ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ๋•Œ ์‚ฌ์šฉ, ์ž…๋ ฅ ๋ฐฐ์—ด์˜ ํ˜•ํƒœ๋ฅผ ์ง€์ •ํ•˜๊ณ , ๋‹ค์–‘ํ•œ ํฌ๊ธฐ์˜ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ๋™์ผํ•œ ํ•จ์ˆ˜๊ฐ€ ์ž‘๋™ํ•˜๋„๋ก ํ•œ๋‹ค.
from numba import guvectorize

@guvectorize(["(float64[:], float64[:])"], "(n)->(n)")
def vectorized_function(input_array, output_array):
    for i in range(input_array.shape[0]):
        output_array[i] = input_array[i] * 2

 

@vectorize

  • ๋ฐฐ์—ด ์—ฐ์‚ฐ์„ ๋ฒกํ„ฐํ™”ํ•˜์—ฌ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•œ๋‹ค. ์Šค์นผ๋ผ ํ•จ์ˆ˜๋ฅผ ๋ฒกํ„ฐํ™”ํ•˜์—ฌ ์ž…๋ ฅ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ์‹คํ–‰ ํ•  ์ˆ˜ ์žˆ๋‹ค.
from numba import vectorize

@vectorize([float64(float64)])
def vectorized_scalar_function(x):
    return x * 2

 

@stencil

  • ๊ฒฉ์ž ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ์Šคํ…์‹ค ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค. ์ฃผ๋กœ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ๋‚˜ ๊ณผํ•™์  ๊ณ„์‚ฐ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.
from numba import stencil

@stencil
def stencil_function(a):
    return a[0, 0] + a[1, 0] + a[0, 1] + a[1, 1]

 

@prange

  • ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ๋ฐ˜๋ณต๋ฌธ์„ ์ž‘์„ฑํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค. for๋ฃจํ”„๋ฅผ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.
from numba import njit, prange

@njit
def parallel_sum(arr):
    total = 0.0
    for i in prange(arr.size):
        total += arr[i]
    return total

 

728x90
๋ฐ˜์‘ํ˜•