PyInstaller를 통한 PyTorch 모델 서빙을 위한 EXE 파일 생성시 발생되는 이슈 고치기

jh.cin·2020년 10월 20일
1

최근 PyTorch를 통해서 모델을 만들고 로컬 컴퓨터에 EXE 파일을 실행할때 발생되는 이슈들이 있었다.

첫번째로는

PyInstaller를 통해서 EXE 생성시 DLL파일들에 대한 의존성 많은 라이브러리가 포함된 경우 하나의 파일로 생성해주는 --onefile 플래그 사용을 자제하는것을 추천한다. 플래그 사용해서 EXE 파일 생성시 자주 DLL이 포함되지 않고(?) 하나의 파일로 만들어주는 상황이 발생한다.

두번째로는

윈도우에서 Python 파일을 PyInstaller를 통해 EXE로 만들고나서 실행하면 module not found에러가 생긴다.

1. 본 문제는 중간 파일로 생기는 .spec 파일에서 hiddenimports에 찾지 못한 모듈들을 차례대로 넣어준다

a = Analysis(['run.py'],
pathex=['C:\???','C:\???\???'],
binaries=[],
datas=[],
hiddenimports=[],##<== 찾지 못한 모듈을 입력 ex) hiddenimports=['DCNv2','pynput']
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)

2. spec 파일을 수정후 아래 커맨드를 통해서 EXE을 생성한다.

pyinstaller filename.spec ## 실행

세번째로는

CUDA error: no kernel image is available for execution on the device 이다.
(PyTorch에서 새로운 레이어나 모듈을 적용하기 위해) NVCC에서 컴파일링시 해당 GPU의 Capability를 지원하지 않고 모듈을 만들었기 때문인데,
해당 링크를 참고하여 적합한 GPU의 Capability를 지원하자.

※주의할점은 모듈을 생성하고 다시 EXE 파일 작업시, PyInstaller를 통해 이전에 만들어놨던 실행파일이나 build,dist 폴더가 있다면 처음부터 지우고 깨끗하게 EXE 파일을 생성하자.

Python에서 setup.py을 통해 cuda 파일을 컴파일링시 Code(DCNv2 모듈)예제

import os
import glob

import torch

from torch.utils.cpp_extension import CUDA_HOME
from torch.utils.cpp_extension import CppExtension
from torch.utils.cpp_extension import CUDAExtension

from setuptools import find_packages
from setuptools import setup

requirements = ["torch", "torchvision"]


def get_extensions():
    this_dir = os.path.dirname(os.path.abspath(__file__))
    extensions_dir = os.path.join(this_dir, "src")

    main_file = glob.glob(os.path.join(extensions_dir, "*.cpp"))
    source_cpu = glob.glob(os.path.join(extensions_dir, "cpu", "*.cpp"))
    source_cuda = glob.glob(os.path.join(extensions_dir, "cuda", "*.cu"))
    
    # os.environ["CC"] = "g++"
    sources = main_file + source_cpu
    extension = CppExtension
    extra_compile_args = {"cxx": []}
    define_macros = []

    
    if torch.cuda.is_available() and CUDA_HOME is not None:
        extension = CUDAExtension
        sources += source_cuda
        define_macros += [("WITH_CUDA", None)]
        extra_compile_args["nvcc"] = [
            "-DCUDA_HAS_FP16=1",
            "-D__CUDA_NO_HALF_OPERATORS__",
            "-D__CUDA_NO_HALF_CONVERSIONS__",
            "-D__CUDA_NO_HALF2_OPERATORS__",
        ]
    else:
        #raise NotImplementedError('Cuda is not available')
        pass
        
##핵심코드----------
    gencodes = [
    '-gencode', 'arch=compute_52,code=sm_52',
    '-gencode', 'arch=compute_60,code=sm_60',
    '-gencode', 'arch=compute_61,code=sm_61',
    '-gencode', 'arch=compute_70,code=sm_70',
    '-gencode', 'arch=compute_75,code=sm_75',
    '-gencode', 'arch=compute_75,code=compute_75',]		
    extra_compile_args["nvcc"] += gencodes
##--------------

		
    sources = [os.path.join(extensions_dir, s) for s in sources]
    include_dirs = [extensions_dir]
    ext_modules = [
        extension(
            "_ext",
            sources,
            include_dirs=include_dirs,
            define_macros=define_macros,
            extra_compile_args=extra_compile_args,
        )
    ]
    return ext_modules

setup(
    name="DCNv2",
    version="0.1",
    author="charlesshang",
    url="https://github.com/charlesshang/DCNv2",
    description="deformable convolutional networks",
    packages=find_packages(exclude=("configs", "tests",)),
    # install_requires=requirements,
    ext_modules=get_extensions(),
    cmdclass={"build_ext": torch.utils.cpp_extension.BuildExtension},
)
profile
그냥 프로그래머

0개의 댓글