[Python] 시간 및 메모리 체크 Template

2024. 1. 5. 01:28Developers 공간 [Shorts]/Software Basic

728x90
반응형
<분류>
A. 수단
- OS/Platform/Tool : Linux, Kubernetes(k8s), Docker, AWS
- Package Manager : node.js, yarn, brew, 
- Compiler/Transpillar : React, Nvcc, gcc/g++, Babel, Flutter

- Module Bundler  : React, Webpack, Parcel

B. 언어
- C/C++, python, Javacsript, Typescript, Go-Lang, CUDA, Dart, HTML/CSS

C. 라이브러리 및 프레임워크 및 SDK
- OpenCV, OpenCL, FastAPI, PyTorch, Tensorflow, Nsight

 


1. What? (현상)

이번 글에서는 많이 사용하는 python에서 시간과 메모리를 확인하는 모듈을 기록해두려고합니다.


2. Why? (원인)

  • X

3. How? (해결책)

1. Parent(부모) module 만들기

다양한 곳에 활용할 부모 모듈을 먼저 만들어두고자 합니다.

 

일반합과 제곱합을 유지하고 나중에 평균(average)과 표준편차(standard deviation)를 구하도록 구현했습니다. 표준편차를 구하는 식은 아시다시피 아래와 같습니다.

$$ \sqrt{\mathbb{E}(x^2)-(\mathbb{E}(x))^2}$$

import math,sys
from typing import Union

class HistoryCheck:
    def __init__(self):
    	self.values={}
    def initFloat(self,key:str):
        self.values[key]={
            "num":0,
            "sum":0.0,
            "square":0.0
        }

    def initInt(self,key:str):
        self.values[key]={
            "num":0,
            "sum":0,
            "square":0
        }

    def updateBasic(self, key:str, value:Union[float,int]):
        if((self.values[key]['sum'] + value) < sys.float_info.max and 
        (self.values[key]['square'] + value*value) < sys.float_info.max and
        (self.values[key]['num'] +1) < sys.maxsize):
            self.values[key]['sum'] = self.values[key]['sum'] + value
            self.values[key]['square'] = self.values[key]['square'] + value*value
            self.values[key]['num'] = self.values[key]['num'] +1

    def printBasic(self, key:str, title:str="", delimeter:str="", with_full=None):
        num=self.values[key]['num']
        if num==0:
        	print("Nothing to print")
        	return
        sum = self.values[key]['sum']
        avg = sum/float(num)
        if num != 1:
        	std_dev = math.sqrt((self.values[key]['square']*num - sum*sum)/(num*(num-1)))
        else:
        	std_dev = .0
        if with_full:
        	print("{:<28} ({:<10}) —- avg: {:8.3f}{}/{}{} // std_dev: {:5.2f}{} // count: {}".format(title, key, avg, delimeter, with_full, delimeter, std_dev, delimeter, num))
        else : 
        	print("{:<28} ({:<10}) —- avg: {:8.3f}{} // std_dev: {:5.2f}{} // count: {}".format(title, key, avg, delimeter, std_dev, delimeter, num))

 

2. 시간측정 모듈

이제 예를 들어 시간을 측정하는 모듈을 만들어보고자 합니다. 

"preprocess → encoder" 로 동작하는 순서라고 할때 아래와 같이 구현했습니다.

class TimeCheck(HistoryCheck):
    def __init__(self, ):
        super().__init__()
        self.start = 00.0
        self.initFloat("preprocess")
        self.currentPre=0.0
        self.initFloat("encoder")
        self.currentEnc = 0.0

    def updateStart(self, time:float):
    	self.start = time*1000.0
    def update(self, key:str, time:float):
        if key=="preprocess":
            self.currentPre = time*1000.0
            self.updateBasic(key,self.currentPre - self.start)
        elif key=="encoder":
            self.currentEnc = time*1000.0
            self.updateBasic(key,self.currentEnc - self.currentPre)
        else:
        	raise Exception("ERROR")
    def printAll(self):
        for key in self.values.keys():
        	self.printBasic(key,title="[TK][Debug] Elapsed Time", delimeter="ms")

자 이제 위에서 만들 모듈을 사용해 시간을 측정해보겠습니다.

import time
debug_time = TimeCheck()
debug_time.updateStart(time.time())
debug_time.update('preprocess', time.time())
debug_time.update('encoder', time.time())

debug_time.printAll()

 

3. 메모리측정 모듈

이번엔 다른 예로 메모리를 측정하는 모듈을 만들어보고자 합니다.

이번엔 어떤 메모리를 먼저 측정하게 될지 모른다는 가정하에 아래와 같이 구현했습니다.

class MemoryCheck(HistoryCheck):
    def __init__(self, init_free:float, init_full:float):
        super().__init__()
        self.initFloat("preprocess")
        self.currentPre=0.0
        self.initFloat("encoder")
        self.currentEnc=0.0
        self.initFloat("total")
        self.init_full = init_full/1024.0/1024.0
        self.init_mem = (init_full-init_free)/1024.0/1024.0
        print("{}, {}".format(self.init_mem, self.init_full))
    def update(self, key:str, free:float):
        if key=="preprocess":
            self.currentPre = self.init_full - free/1024.0/1024.0 - self.currentEnc - self.init_mem
            self.updateBasic(key,self.currentPre)
        elif key=="encoder":
            self.currentEnc = self.init_full - free/1024.0/1024.0 - self.currentPre - self.init_mem
            self.updateBasic(key,self.currentEnc)
        else:
        	raise Exception("ERROR")
        self.updateBasic('total',self.init_full - free/1024.0/1024.0 - self.init_mem)

    def printAll(self):
        for key in self.values.keys():
     	   self.printBasic(key,title="[TK][Debug] Memory Used", delimeter="MB", with_full=self.init_full)

 

메모리 측정을 위해 pycuda를 설치한 후,

pip3 install pycuda

아래와 같이 위에서 만든 모듈을 실행시켜 보았습니다.

import pycuda.driver as cuda
import pycuda.autoinit
debug_mem = MemoryCheck(cuda.mem_get_info()[0], cuda.mem_get_info()[1])
debug_mem.update('preprocess', cuda.mem_get_info()[0])
debug_mem.update('encoder', cuda.mem_get_info()[0])
debug_mem.printAll()

 

728x90
반응형