AI 탐구노트

python-smi : 프로그램에서 GPU 현황 확인 본문

기술 팁

python-smi : 프로그램에서 GPU 현황 확인

42morrow 2024. 10. 21. 12:24

 

 

 

필요성

 

NVIDIA GPU를 사용하면서, AI 모델 추론이나 학습을 시키면서 남아 있거나 현재 사용 중인 GPU 현황이 궁금했던 적이 있을 겁니다. 모델 하나를 더 로딩하려다가 GPU 사용량 초과, 메모리 부족 등으로 인해 문제가 생기는 경우가 발생할 수 있기 때문이죠. 프레임워크에서 알아서 완벽하게 처리를 해 주면 좋겠지만 그렇지 못한 경우들이 종종 나타날 수 있기 때문에 서비스를 제공하는 입장에서는 항상 모니터링을 할 수 있도록 준비를 해 두는 것이 필요할 수 있습니다. 

 

 

방법

GPU 현황을 확인하는 방법은 다음과 같은 것들이 있습니다 .

 

1.별도의 창에서 nvidia-smi, nvitop 과 같은 외부 도구를 이용해 별도로 모니터링

2.pycuda, pynvml 등의 NVIDIA python 패키지를 이용하는 방법

3.python-smi 패키지를 이용하는 방법

 

 

위 가운데 1번은 python 내에서 하려면 subprocess를 별도로 생성하고 실행 결과를 pipe로 받아오는 작업을 해야 합니다. 즉, 외부 프로그램에서 실행하고 그 결과만 가져오는건데 일단 깔끔하진 않죠... 아래는 그 예시입니다. 

import subprocess

def get_gpu_info():
    result = subprocess.run(['nvidia-smi'], stdout=subprocess.PIPE)
    print(result.stdout.decode('utf-8'))

get_gpu_info()

 

 

2번 방법은 강력하긴 한데, 아무래도 기본적인 기술 이해가 있어야 사용하기 편합니다. 사용을 위해서는 먼저 아래와 같이 패키지를 설치합니다. (아래는 pynvml 을 이용하는 예시)

$ pip install nvidia-ml-py3

 

테스트 예시는 다음과 같습니다. 

import pynvml

def get_gpu_usage():
    pynvml.nvmlInit()
    device_count = pynvml.nvmlDeviceGetCount()
    
    for i in range(device_count):
        handle = pynvml.nvmlDeviceGetHandleByIndex(i)
        mem_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
        gpu_utilization = pynvml.nvmlDeviceGetUtilizationRates(handle)
        
        print(f"GPU {i}:")
        print(f"  Memory Usage: {mem_info.used / 1024**2:.2f} MB / {mem_info.total / 1024**2:.2f} MB")
        print(f"  GPU Utilization: {gpu_utilization.gpu}%")
    
    pynvml.nvmlShutdown()

get_gpu_usage()

 

 

그런데 반해 이번에 소개드릴 3번 python-smi는 nvidia-smi 사용과 같은 방식이라 어렵지 않고 명령어 자체도 직관적이라는 장점이 있습니다.  Python-smi에 대한 추가 세부적인 사용법은 py-smi github repository에서 확인하실 수 있습니다. 참고로 Repository 관리 측인 Anwser.ai는 fastAI를 만든 Jeremy Howard가 운영하고 있는 곳이기도 합니다. 

 

python-smi 사용법

 

우선 필요한 패키지를 설치합니다. 

$ pip install python-smi

 

 

python 코드 상에서 사용하는 방법은 직관적이라 좋아 보입니다. 

from py_smi import NVML
nv = NVML()

# 버전 확인
nv.driver_version, nv.cuda_version

# GPU 정보 추출
nv.utilization() # 사용률 정보 : GPU번호, 메모리, 인코딩, 디코딩
nv.power()	     # 전원 사용률, 최대전력
nv.processes()   # 사용 중인 process : pid, name, memory 등


# GPU serial 번호 추출 포함인데 이 부분엣 현재 오류 발생 중
nv.info({{gpu no})
nv.dmon()        # 모니터링 : 파워, 온도, sm, mem, enc, dec, mclk, pclk 등 (nvidia-smi dmon 과 유사)
...

 

 

시행착오-1

제 경우, 일부 함수 사용에 있어 아래와 같이 nvmlDeviceGetName() 함수 호출 시 오류가 발생합니다. 이 값은 'nvidia-smi -L' 커맨드를 통해 추출할 수 있는 GPU UUID 값인 듯 한데... 왜 거기서 걸리는 것인지는 아직은 확인하지 못했습니다. 

File ~/anaconda3/envs/yolov10/lib/python3.11/site-packages/py_smi/core.py:37, in info(self, i)
     33 \"Basic information about GPU `i`\"
     34 h = self[i]
     35 return _Info(
     36     name=nvmlDeviceGetName(h),
---> 37     serial=nvmlDeviceGetSerial(h),
     38     uuid=nvmlDeviceGetUUID(h),
     39     persistence_mode=nvmlDeviceGetPersistenceMode(h),
     40     bus_id=nvmlDeviceGetPciInfo(h).busId,
     41     display_active=nvmlDeviceGetDisplayActive(h),
     42     performance_state=nvmlDeviceGetPerformanceState(h),
     43     fan_speed=nvmlDeviceGetFanSpeed(self[i]),
     44     temperature=nvmlDeviceGetTemperature(self[i], NVML_TEMPERATURE_GPU),
     45     compute_mode=nvmlDeviceGetComputeMode(h))

File ~/anaconda3/envs/yolov10/lib/python3.11/site-packages/pynvml.py:2175, in convertStrBytes.<locals>.wrapper(*args, **kwargs)
   2171 @wraps(func)
   2172 def wrapper(*args, **kwargs):
   2173     # encoding a str returns bytes in python 2 and 3
   2174     args = [arg.encode() if isinstance(arg, str) else arg for arg in args]
-> 2175     res = func(*args, **kwargs)
   2176     # In python 2, str and bytes are the same
   2177     # In python 3, str is unicode and should be decoded.
   2178     # Ctypes handles most conversions, this only effects c_char and char arrays.
   2179     if isinstance(res, bytes):

File ~/anaconda3/envs/yolov10/lib/python3.11/site-packages/pynvml.py:2519, in nvmlDeviceGetSerial(handle)
   2517 fn = _nvmlGetFunctionPointer(\"nvmlDeviceGetSerial\")
   2518 ret = fn(handle, c_serial, c_uint(NVML_DEVICE_SERIAL_BUFFER_SIZE))
-> 2519 _nvmlCheckReturn(ret)
   2520 return c_serial.value

File ~/anaconda3/envs/yolov10/lib/python3.11/site-packages/pynvml.py:979, in _nvmlCheckReturn(ret)
    977 def _nvmlCheckReturn(ret):
    978     if (ret != NVML_SUCCESS):
--> 979         raise NVMLError(ret)
    980     return ret

NVMLError_NotSupported: Not Supported"
}

 

 

이번 글에서는 python 코드에서 nvidia-smi 대용 기능을 사용해서 GPU 현황 정보를 추출하는 방법을 살펴봤습니다.