본문 바로가기
AI 활용

[제조 AI] 2-2) 로컬 AI 인프라 구축 - (실습)제조업 AI 실제 개발환경 구축

by 피크나인 2025. 8. 18.

홈  / AI활용  / 제조AI  /  2-2) 로컬 AI 인프라 구축 - (실습)제조업  AI 실제 개발환경 구축

AI 개발환경 완전 구축 실습 가이드 - 개발용 하드웨어 기준 실제 설치부터 검증까지

앞서 '2-1) 로컬 AI 인프라 구축 - 하드웨어에서 개발환경 구축까지' 편에서 다룬 하드웨어 구성 이론을 바탕으로, 이제 실제 개발용 시스템에서 AI 개발환경을 구축해보겠습니다.

 

우리가 선택한 개발용 구성은 RTX 4090 24GB 듀얼 GPU, AMD Threadripper PRO 5975WX CPU, 128GB ECC 메모리로 구성된 시스템입니다.

이 하드웨어는 GPT-2 규모의 모델 훈련이 가능하고, 실시간 추론 서비스에서 100명 이상의 동시 사용자를 지원할 수 있는 성능을 제공합니다. 단순히 이론만 아는 것과 실제로 설치하고 설정하는 것은 완전히 다른 경험입니다. 이번 실습을 통해 여러분은 실무에서 바로 사용할 수 있는 완전한 AI 개발환경을 손으로 직접 구축하게 됩니다.

본 가이드는 실제 하드웨어를 기준으로 작성되었으므로, 설명하는 모든 과정을 그대로 따라하실 수 있습니다. 실제 구축시 소요되는 시간도 같이 표기해 드립니다. 직접 구축시 필요이상의 시간이 소요되는 경우는 설치의 정확성 및 검증을 반드시 수행하시는 것이 좋습니다.
 

실습이 끝나면 여러분의 시스템에서 PyTorch와 TensorFlow가 듀얼 GPU를 완벽하게 활용하며, Docker 컨테이너 환경에서 안정적으로 AI 모델을 개발할 수 있는 환경이 완성됩니다. 이는 단순한 학습 환경이 아닌, 실제 제품 개발에 바로 투입할 수 있는 프로덕션 수준의 개발환경입니다.

 

개발용 AI 워크스테이션 - RTX 4090 듀얼 GPU와 Threadripper CPU로 구성된 실제 개발 환경
개발용 AI 워크스테이션 - RTX 4090 듀얼 GPU와 Threadripper CPU로 구성된 실제 개발 환경


1. 선택된 하드웨어 구성 확인

제조AI  개발용으로선정한 개발용 하드웨어 구성이 올바르게 조립되었는지 확인하고, 각 구성 요소가 정상적으로 인식되는지 검증합니다. 시스템 부팅부터 기본적인 하드웨어 정보 수집까지 진행하며, RAID 구성 계획을 수립합니다. 이 단계를 완료하면 후속 소프트웨어 설치를 위한 안정적인 하드웨어 기반이 준비됩니다.

예상 소요시간은 약 30분~1시간 정도이며, 혹시 하드웨어 문제가 발견되면 지금 단계에서 해결해야 합니다.

개발용 시스템 사양

2편에서 검토한 예산별 구성 중 개발용(1,200만원) 구성을 실제로 선택했습니다.

이 구성은 소규모 팀이나 스타트업에서 본격적인 AI 개발을 진행하기에 최적화된 사양입니다.

 

확정된 하드웨어 사양:

  • CPU: AMD Threadripper PRO 5975WX (32코어/64쓰레드)
  • GPU: NVIDIA RTX 4090 24GB × 2장 (NVLink 연결)
  • RAM: 128GB DDR4-3200 ECC (32GB × 4)
  • 스토리지: 2TB NVMe SSD × 2 (RAID 0) + 8TB HDD × 2 (RAID 1)
  • 메인보드: TRX50 칩셋 (다중 GPU 지원)
  • 전원: 1600W 80+ Platinum

예상 성능 지표:

  • 모델 훈련: GPT-2 급 모델 3일 내 완료
  • 동시 추론: 100+ requests/sec
  • 메모리 효율: 전체 데이터셋 메모리 로딩 가능
  • 확장성: 향후 GPU 2장 추가 확장 가능

시스템 조립 완료 상태 확인

하드웨어 조립이 완료되었다고 가정하고, 시스템이 정상적으로 부팅되는지 확인해보겠습니다.

 

부팅 후 기본 확인 사항

아직 운영체제가 설치가 안된 경우는 운영체제(Ubuntu)를 설치하고 확인해주세요. 구매 또는 임대한 시스템과의 시스템 사양이 일치하는지 확인합니다. (하드웨어 핵심 구성요소 : CPU, Memory, GPU(2대의 GPU 인식여부), SSD 등)

# CPU 정보 확인
lscpu | grep -E "Model name|CPU\(s\)|Thread"

# 메모리 확인
free -h

# 스토리지 확인
lsblk

# GPU 기본 인식 확인 (드라이버 설치 전)
lspci | grep -i nvidia

 


2. 운영체제 설치 및 기본 설정

Ubuntu 22.04 LTS를 설치하고 AI 개발에 최적화된 기본 설정을 완료합니다.

단순한 OS 설치를 넘어서 고성능 스토리지를 위한 RAID 구성과 시스템 성능 튜닝까지 진행합니다. 듀얼 NVMe SSD로 RAID 0을 구성하여 데이터 처리 속도를 극대화하고, HDD로 RAID 1을 구성하여 백업 안정성을 확보합니다. 이 과정을 완료하면 AI 워크로드에 최적화된 견고한 운영체제 기반이 구축되며, 예상 소요시간은 약 2시간 정도입니다.

Ubuntu 22.04 LTS 설치

AI 개발에 최적화된 운영체제 설치를 진행합니다.

Ubuntu 22.04 LTS는 NVIDIA 드라이버와 CUDA 호환성이 뛰어나며, 대부분의 AI 프레임워크를 공식 지원합니다.

 

설치 과정:

  1. Ubuntu 22.04 LTS 다운로드
    • 공식 사이트에서 Server 버전 다운로드
    • USB 부팅 디스크 생성
  2. 설치 옵션 선택
    • 언어: English (AI 개발 도구 호환성)
    • 키보드: Korean
    • 네트워크: 자동 설정
    • 스토리지: 수동 파티션 설정

추천 파티션 구성:

/boot/efi    : 512MB (EFI System)
/            : 100GB (루트 파티션)
/home        : 나머지 (사용자 데이터)
swap         : 32GB (메모리 크기의 1/4)

주의사항: RAID 구성은 설치 후 별도로 진행합니다.

시스템 기본 설정 및 최적화

설치 완료 후 AI 개발에 최적화된 시스템 설정을 적용합니다.

# 시스템 업데이트
sudo apt update && sudo apt upgrade -y

# 필수 개발 도구 설치
sudo apt install -y build-essential git curl wget vim htop tree \
    software-properties-common apt-transport-https ca-certificates \
    gnupg lsb-release python3-pip

# SSH 서버 활성화 (원격 개발용)
sudo systemctl enable ssh
sudo systemctl start ssh

# 방화벽 기본 설정
sudo ufw enable
sudo ufw allow ssh
sudo ufw allow 8888  # Jupyter
sudo ufw allow 8000  # API Server

# 사용자를 sudo 그룹에 추가
sudo usermod -aG sudo $USER

 

성능 최적화 설정:

# CPU 성능 모드 설정
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

# 메모리 스왑 최소화 (AI 워크로드 최적화)
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf

# 파일 디스크립터 한도 증가
echo '* soft nofile 1048576' | sudo tee -a /etc/security/limits.conf
echo '* hard nofile 1048576' | sudo tee -a /etc/security/limits.conf

# 설정 적용
sudo sysctl -p

스토리지 RAID 구성

개발용 시스템의 성능과 안정성을 위해 RAID를 구성합니다. 개발자 선호 구성으로 해도 관계 없으나, 성능 및 안전성을 고려한 RAID구성을 추천드립니다.

 

RAID 구성 계획

  • RAID 0 (성능): 2TB NVMe SSD × 2 → 4TB 고성능 스토리지
  • RAID 1 (안정성): 8TB HDD × 2 → 8TB 백업 스토리지
# RAID 도구 설치
sudo apt install mdadm -y

# NVMe SSD RAID 0 구성 (고성능 작업 공간)
sudo mdadm --create /dev/md0 --level=0 --raid-devices=2 /dev/nvme0n1 /dev/nvme1n1

# HDD RAID 1 구성 (백업 및 아카이브)
sudo mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sda /dev/sdb

# 파일시스템 생성
sudo mkfs.ext4 /dev/md0  # 고성능 스토리지
sudo mkfs.ext4 /dev/md1  # 백업 스토리지

# 마운트 포인트 생성 및 설정
sudo mkdir -p /workspace /backup
sudo mount /dev/md0 /workspace
sudo mount /dev/md1 /backup

# 자동 마운트 설정
echo '/dev/md0 /workspace ext4 defaults 0 0' | sudo tee -a /etc/fstab
echo '/dev/md1 /backup ext4 defaults 0 0' | sudo tee -a /etc/fstab

 

검증: 다음 명령어로 RAID 상태를 확인하세요.

cat /proc/mdstat
df -h | grep -E "workspace|backup"

3. NVIDIA 드라이버 및 CUDA 설치

RTX 4090 듀얼 GPU를 완벽하게 활용하기 위한 NVIDIA 드라이버 535와 CUDA 12.1을 설치합니다.

기존 Nouveau 드라이버를 완전히 제거하고, 최신 NVIDIA 드라이버를 설치한 후 AI 프레임워크 호환성을 위한 CUDA 툴킷과 cuDNN을 구성합니다. 이 과정에서 듀얼 GPU가 모두 정상적으로 인식되고 CUDA 가속이 활성화되는지 검증합니다. 완료 후에는 nvidia-smi 명령어로 두 개의 RTX 4090이 완벽하게 인식되며, 예상 소요시간은 약 1시간 정도입니다.

기존 드라이버 정리 및 준비

RTX 4090 듀얼 GPU 환경에서 안정적인 드라이버 설치를 위해 시스템을 준비합니다.

# 기존 NVIDIA 관련 패키지 완전 제거
sudo apt remove --purge nvidia* libnvidia*
sudo apt autoremove

# Nouveau 드라이버 비활성화 (오픈소스 NVIDIA 드라이버)
echo 'blacklist nouveau' | sudo tee -a /etc/modprobe.d/blacklist-nouveau.conf
echo 'options nouveau modeset=0' | sudo tee -a /etc/modprobe.d/blacklist-nouveau.conf

# initramfs 업데이트 및 재부팅
sudo update-initramfs -u
sudo reboot

 

재부팅 후 Nouveau 비활성화 확인

lsmod | grep nouveau  # 출력이 없어야 함

NVIDIA 드라이버 535 설치

RTX 4090을 완벽하게 지원하는 최신 드라이버를 설치합니다.

# NVIDIA 공식 저장소 추가
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.0-1_all.deb
sudo dpkg -i cuda-keyring_1.0-1_all.deb
sudo apt update

# 권장 드라이버 버전 확인
ubuntu-drivers devices

# NVIDIA 드라이버 535 설치
sudo apt install -y nvidia-driver-535-server

# 시스템 재부팅
sudo reboot

 

드라이버 설치 검증

# 기본 GPU 인식 확인
nvidia-smi

# 듀얼 GPU 구성 확인
nvidia-smi -L

 

예상 출력 결과

GPU 0: NVIDIA GeForce RTX 4090 (UUID: GPU-xxx)
GPU 1: NVIDIA GeForce RTX 4090 (UUID: GPU-yyy)

CUDA 12.1 Toolkit 설치

AI 프레임워크와 호환되는 CUDA 버전을 설치합니다.

# CUDA 12.1 런파일 다운로드
cd /tmp
wget https://developer.download.nvidia.com/compute/cuda/12.1.0/local_installers/cuda_12.1.0_530.30.02_linux.run

# 실행 권한 부여
chmod +x cuda_12.1.0_530.30.02_linux.run

# CUDA 설치 (드라이버는 제외, 툴킷만 설치)
sudo ./cuda_12.1.0_530.30.02_linux.run --silent --toolkit --no-opengl-libs

 

환경변수 설정

# CUDA 경로 설정
echo 'export PATH=/usr/local/cuda-12.1/bin${PATH:+:${PATH}}' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}' >> ~/.bashrc
echo 'export CUDA_HOME=/usr/local/cuda-12.1' >> ~/.bashrc

# 설정 적용
source ~/.bashrc

 

CUDA 설치 검증

# CUDA 컴파일러 확인
nvcc --version

# GPU 상세 정보 확인
nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv

cuDNN 8.9.2 설치

딥러닝 성능 최적화를 위한 cuDNN 라이브러리를 설치합니다.

# cuDNN 다운로드 (NVIDIA 개발자 계정 필요)
# https://developer.nvidia.com/cudnn 에서 수동 다운로드 후 서버로 전송

# 예시: cuDNN 8.9.2 for CUDA 12.1
tar -xzf cudnn-linux-x86_64-8.9.2.26_cuda12-archive.tar.xz

# CUDA 디렉토리로 파일 복사
sudo cp cudnn-linux-x86_64-8.9.2.26_cuda12-archive/include/cudnn*.h /usr/local/cuda-12.1/include/
sudo cp cudnn-linux-x86_64-8.9.2.26_cuda12-archive/lib/libcudnn* /usr/local/cuda-12.1/lib64/

# 권한 설정
sudo chmod a+r /usr/local/cuda-12.1/include/cudnn*.h /usr/local/cuda-12.1/lib64/libcudnn*

 

cuDNN 설치 확인

cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2

4. Python 환경 및 AI 프레임워크 설치

PyTorch와 TensorFlow 모두 듀얼 GPU를 완벽하게 활용할 수 있는 AI 개발 환경을 구축합니다.

Conda를 활용하여 독립적인 가상환경을 생성하고, 각각에 최적화된 AI 프레임워크를 설치합니다. 설치 완료 후에는 실제 멀티 GPU 훈련 코드를 실행하여 두 개의 RTX 4090이 동시에 활용되는지 검증합니다. 이 단계를 완료하면 대규모 모델 훈련과 고성능 추론이 가능한 완전한 AI 개발 환경이 준비되며, 예상 소요시간은 약 1.5시간 정도입니다.

4.1 Python 3.11 및 Conda 환경 구성

안정적인 AI 개발을 위한 Python 환경을 구성합니다.

# Miniconda 다운로드 및 설치
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
chmod +x Miniconda3-latest-Linux-x86_64.sh
./Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda3

# PATH 설정
echo 'export PATH="$HOME/miniconda3/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

# conda 초기화
conda init bash
source ~/.bashrc

# conda 최적화 설정
conda config --set auto_activate_base false
conda config --add channels conda-forge
conda config --add channels nvidia
conda config --set channel_priority strict

 

AI 개발용 가상환경 생성

# PyTorch 환경 생성
conda create -n ai-dev python=3.11 -y
conda activate ai-dev

# 기본 과학 계산 패키지 설치
conda install -y numpy pandas matplotlib seaborn scikit-learn \
    jupyter jupyterlab ipykernel notebook

PyTorch 듀얼 GPU 환경 설치

RTX 4090 듀얼 GPU를 완벽하게 활용하는 PyTorch 설치를 진행합니다.

# PyTorch 2.1 with CUDA 12.1 설치
conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia

# 추가 AI 라이브러리 설치
pip install transformers datasets accelerate
pip install opencv-python pillow albumentations
pip install wandb mlflow tensorboard
pip install fastapi uvicorn

 

듀얼 GPU 설치 검증

# GPU 인식 및 성능 테스트
import torch
import time

print(f"PyTorch 버전: {torch.__version__}")
print(f"CUDA 사용 가능: {torch.cuda.is_available()}")
print(f"GPU 개수: {torch.cuda.device_count()}")

# 각 GPU 정보 출력
for i in range(torch.cuda.device_count()):
    print(f"GPU {i}: {torch.cuda.get_device_name(i)}")
    print(f"  메모리: {torch.cuda.get_device_properties(i).total_memory / 1024**3:.1f} GB")

# 듀얼 GPU 성능 테스트
def test_dual_gpu_performance():
    device0 = torch.device('cuda:0')
    device1 = torch.device('cuda:1')
    
    # 각 GPU에서 행렬 연산 수행
    a0 = torch.randn(4000, 4000, device=device0)
    b0 = torch.randn(4000, 4000, device=device0)
    
    a1 = torch.randn(4000, 4000, device=device1)
    b1 = torch.randn(4000, 4000, device=device1)
    
    start_time = time.time()
    
    # 동시 연산 실행
    c0 = torch.matmul(a0, b0)
    c1 = torch.matmul(a1, b1)
    
    torch.cuda.synchronize()
    end_time = time.time()
    
    print(f"듀얼 GPU 행렬 곱셈 시간: {end_time - start_time:.4f}초")
    print(f"GPU 0 메모리 사용량: {torch.cuda.memory_allocated(0) / 1024**3:.2f} GB")
    print(f"GPU 1 메모리 사용량: {torch.cuda.memory_allocated(1) / 1024**3:.2f} GB")

test_dual_gpu_performance()

TensorFlow 환경 구성

PyTorch와 별도의 TensorFlow 환경을 구성합니다.

# TensorFlow 전용 환경 생성
conda create -n tf-dev python=3.11 -y
conda activate tf-dev

# TensorFlow 2.13 설치
pip install tensorflow==2.13.0
pip install tensorflow-datasets keras-tuner

# 공통 라이브러리 설치
pip install numpy pandas matplotlib seaborn scikit-learn
pip install opencv-python pillow
pip install jupyter jupyterlab ipykernel

 

TensorFlow 듀얼 GPU 검증

import tensorflow as tf
import time

print(f"TensorFlow 버전: {tf.__version__}")
print("사용 가능한 GPU:", tf.config.list_physical_devices('GPU'))

# GPU 메모리 증가 허용 설정
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
    try:
        for gpu in gpus:
            tf.config.experimental.set_memory_growth(gpu, True)
        print("GPU 메모리 증가 허용 설정 완료")
    except RuntimeError as e:
        print(f"GPU 설정 오류: {e}")

# 듀얼 GPU 분산 전략 테스트
def test_tf_multi_gpu():
    strategy = tf.distribute.MirroredStrategy()
    print(f"분산 전략 GPU 개수: {strategy.num_replicas_in_sync}")
    
    with strategy.scope():
        # 간단한 모델 생성
        model = tf.keras.Sequential([
            tf.keras.layers.Dense(512, activation='relu', input_shape=(1000,)),
            tf.keras.layers.Dense(256, activation='relu'),
            tf.keras.layers.Dense(10, activation='softmax')
        ])
        
        model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
        print("듀얼 GPU 분산 모델 생성 완료")

test_tf_multi_gpu()

5. Docker 환경 구성 및 GPU 지원

컨테이너 기반 AI 개발 환경을 구축하여 프로젝트별 독립성과 배포 일관성을 확보합니다.

Docker Engine과 NVIDIA Container Toolkit을 설치하여 컨테이너 내부에서도 듀얼 GPU에 접근할 수 있도록 설정합니다. 설정 완료 후에는 컨테이너 환경에서 GPU 가속이 정상적으로 작동하는지 검증하고, 향후 마이크로서비스 배포를 위한 기반을 마련합니다. 이 과정을 통해 개발 환경의 이식성과 확장성이 크게 향상되며, 예상 소요시간은 약 45분 정도 입니다.

Docker Engine 및 NVIDIA Container Toolkit 설치

컨테이너 기반 AI 개발 환경을 구성합니다.

# Docker 공식 저장소 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Docker 설치
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 사용자를 docker 그룹에 추가
sudo usermod -aG docker $USER
newgrp docker

# Docker 서비스 활성화
sudo systemctl enable docker
sudo systemctl start docker

 

NVIDIA Container Toolkit 설치

# NVIDIA Container Toolkit 저장소 설정
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
   && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
   && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
      sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
      sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

# 패키지 설치
sudo apt update
sudo apt install -y nvidia-container-toolkit

# Docker 데몬 설정 업데이트
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

Docker GPU 지원 검증

듀얼 GPU 환경에서 Docker 컨테이너가 정상적으로 GPU에 접근하는지 확인합니다.

# 모든 GPU 접근 테스트
docker run --rm --gpus all nvidia/cuda:12.1-base-ubuntu20.04 nvidia-smi

# 특정 GPU만 할당 테스트
docker run --rm --gpus '"device=0"' nvidia/cuda:12.1-base-ubuntu20.04 nvidia-smi

# GPU 메모리 제한 테스트
docker run --rm --gpus '"device=0,memory=8g"' nvidia/cuda:12.1-base-ubuntu20.04 nvidia-smi

 

정상 출력 예시

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 535.xx.xx    Driver Version: 535.xx.xx    CUDA Version: 12.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  RTX 4090           Off   | 00000000:41:00.0 Off |                  Off |
| 30%   35C    P8    25W / 450W |      0MiB / 24564MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  RTX 4090           Off   | 00000000:42:00.0 Off |                  Off |
| 30%   34C    P8    24W / 450W |      0MiB / 24564MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

AI 개발용 Docker 이미지 테스트

PyTorch와 TensorFlow를 모두 지원하는 통합 환경을 테스트합니다.

# 통합 AI 개발 컨테이너 실행
docker run -it --gpus all \
    -p 8888:8888 \
    -v /workspace:/workspace \
    pytorch/pytorch:2.1.0-cuda12.1-cudnn8-devel \
    bash

# 컨테이너 내에서 GPU 확인
nvidia-smi
python -c "import torch; print(f'GPU 개수: {torch.cuda.device_count()}')"

6. 개발환경 통합 검증

지금까지 구축한 모든 구성 요소가 통합적으로 완벽하게 작동하는지 종합 검증을 수행합니다.

실제 멀티 GPU 분산 훈련 시나리오를 실행하여 듀얼 RTX 4090의 성능을 측정하고, 메모리 및 연산 성능 벤치마크를 통해 시스템 최적화 상태를 확인합니다. 최종 체크리스트를 통해 모든 하드웨어와 소프트웨어가 예상 성능을 발휘하는지 검증하며, 문제 발견 시 해결 방안을 제시합니다. 이 단계를 완료하면 어떤 AI 프로젝트든 바로 시작할 수 있는 완전한 개발환경이 완성되며, 예상 소요시간은 약 1시간 정도입니다.

멀티 GPU 훈련 환경 테스트

실제 AI 모델을 사용하여 듀얼 GPU 환경이 정상적으로 작동하는지 검증합니다.

 

# distributed_training_test.py
import torch
import torch.nn as nn
import torch.distributed as dist
import torch.multiprocessing as mp
from torch.nn.parallel import DistributedDataParallel as DDP
import time

def setup(rank, world_size):
    """분산 훈련 초기화"""
    dist.init_process_group("nccl", rank=rank, world_size=world_size)
    torch.cuda.set_device(rank)

def cleanup():
    """분산 훈련 정리"""
    dist.destroy_process_group()

def run_training(rank, world_size):
    """분산 훈련 실행"""
    setup(rank, world_size)
    
    # 간단한 CNN 모델 생성
    model = nn.Sequential(
        nn.Conv2d(3, 64, 3, padding=1),
        nn.ReLU(),
        nn.AdaptiveAvgPool2d((1, 1)),
        nn.Flatten(),
        nn.Linear(64, 10)
    ).to(rank)
    
    # DDP로 모델 래핑
    model = DDP(model, device_ids=[rank])
    
    # 더미 데이터 생성
    data = torch.randn(32, 3, 224, 224, device=rank)
    target = torch.randint(0, 10, (32,), device=rank)
    
    # 옵티마이저 설정
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
    criterion = nn.CrossEntropyLoss()
    
    # 훈련 루프
    model.train()
    start_time = time.time()
    
    for step in range(100):
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        
        if step % 20 == 0 and rank == 0:
            print(f"Step {step}, Loss: {loss.item():.4f}")
    
    end_time = time.time()
    
    if rank == 0:
        print(f"듀얼 GPU 훈련 완료! 소요시간: {end_time - start_time:.2f}초")
    
    cleanup()

def main():
    world_size = torch.cuda.device_count()
    print(f"사용 가능한 GPU 개수: {world_size}")
    
    if world_size >= 2:
        mp.spawn(run_training, args=(world_size,), nprocs=world_size, join=True)
        print("멀티 GPU 분산 훈련 테스트 통과!")
    else:
        print("GPU가 2개 미만입니다. 단일 GPU로 테스트합니다.")
        run_training(0, 1)

if __name__ == "__main__":
    main()

메모리 및 성능 벤치마크

시스템의 전반적인 성능을 검증합니다.

# performance_benchmark.py
import torch
import time
import psutil
import numpy as np

def system_info():
    """시스템 정보 출력"""
    print("=== 시스템 정보 ===")
    print(f"CPU 코어: {psutil.cpu_count()}")
    print(f"메모리: {psutil.virtual_memory().total / (1024**3):.1f} GB")
    print(f"GPU 개수: {torch.cuda.device_count()}")
    
    for i in range(torch.cuda.device_count()):
        props = torch.cuda.get_device_properties(i)
        print(f"GPU {i}: {props.name}, {props.total_memory / (1024**3):.1f} GB")

def memory_benchmark():
    """메모리 성능 테스트"""
    print("\n=== 메모리 성능 테스트 ===")
    
    # 대용량 텐서 생성 (각 GPU에 10GB씩 할당)
    tensors = []
    for gpu_id in range(torch.cuda.device_count()):
        with torch.cuda.device(gpu_id):
            # 10GB 텐서 생성 (약 2.5M x 1K 의 float32)
            tensor = torch.randn(2500000, 1000, device=f'cuda:{gpu_id}')
            tensors.append(tensor)
            
            allocated = torch.cuda.memory_allocated(gpu_id) / (1024**3)
            print(f"GPU {gpu_id} 메모리 할당: {allocated:.2f} GB")
    
    # 메모리 정리
    for tensor in tensors:
        del tensor
    torch.cuda.empty_cache()
    print("메모리 정리 완료")

def compute_benchmark():
    """연산 성능 테스트"""
    print("\n=== 연산 성능 테스트 ===")
    
    sizes = [2000, 4000, 8000]
    
    for size in sizes:
        print(f"\n행렬 크기: {size}x{size}")
        
        # 단일 GPU 테스트
        a = torch.randn(size, size, device='cuda:0')
        b = torch.randn(size, size, device='cuda:0')
        
        torch.cuda.synchronize()
        start_time = time.time()
        
        for _ in range(10):
            c = torch.matmul(a, b)
        
        torch.cuda.synchronize()
        single_gpu_time = (time.time() - start_time) / 10
        
        # 듀얼 GPU 병렬 테스트 (가능한 경우)
        if torch.cuda.device_count() >= 2:
            a0 = torch.randn(size, size, device='cuda:0')
            b0 = torch.randn(size, size, device='cuda:0')
            a1 = torch.randn(size, size, device='cuda:1')
            b1 = torch.randn(size, size, device='cuda:1')
            
            torch.cuda.synchronize()
            start_time = time.time()
            
            for _ in range(10):
                c0 = torch.matmul(a0, b0)
                c1 = torch.matmul(a1, b1)
            
            torch.cuda.synchronize()
            dual_gpu_time = (time.time() - start_time) / 10
            
            # FLOPS 계산
            flops = 2 * size**3
            single_gflops = flops / (single_gpu_time * 1e9)
            dual_gflops = 2 * flops / (dual_gpu_time * 1e9)
            
            print(f"  단일 GPU: {single_gpu_time:.4f}s, {single_gflops:.2f} GFLOPS")
            print(f"  듀얼 GPU: {dual_gpu_time:.4f}s, {dual_gflops:.2f} GFLOPS")
            print(f"  성능 향상: {dual_gflops/single_gflops:.2f}배")
        else:
            flops = 2 * size**3
            gflops = flops / (single_gpu_time * 1e9)
            print(f"  단일 GPU: {single_gpu_time:.4f}s, {gflops:.2f} GFLOPS")

def main():
    system_info()
    memory_benchmark()
    compute_benchmark()
    print("\n 모든 성능 테스트 완료!")

if __name__ == "__main__":
    main()

최종 환경 검증 체크리스트

구축된 개발환경이 모든 요구사항을 만족하는지 최종 점검합니다.

 

최종 검증 체크리스트

검증 항목 확인 명령어 기대 결과값
CPU 인식 lscpu | grep "CPU(s)" 32 코어 64 쓰레드
메모리 용량 free -h 125GB 이상 사용 가능
GPU 인식 nvidia-smi -L RTX 4090 2장 인식
CUDA 버전 nvcc --version CUDA 12.1
PyTorch GPU python -c "import torch; print(torch.cuda.device_count())" 2
TensorFlow GPU python -c "import tensorflow as tf; print(len(tf.config.list_physical_devices('GPU')))" 2
Docker GPU docker run --rm --gpus all nvidia/cuda:12.1-base-ubuntu20.04 nvidia-smi GPU 정보 출력
스토리지 성능 hdparm -Tt /dev/md0 1000MB/s 이상

 

성능 기준값

  • GPU 메모리: 각 GPU당 24GB 인식
  • 행렬 곱셈 성능: 4000x4000 기준 0.1초 미만
  • 멀티 GPU 효율성: 1.8배 이상 성능 향상
  • Docker 오버헤드: 5% 미만
# 최종 검증 스크립트 실행
echo "=== AI 개발환경 최종 검증 ==="
echo "1. 하드웨어 확인..."
lscpu | grep -E "Model name|CPU\(s\)"
free -h | grep Mem
nvidia-smi -L

echo -e "\n2. 소프트웨어 확인..."
nvcc --version
python --version
docker --version

echo -e "\n3. AI 프레임워크 확인..."
conda activate ai-dev
python -c "import torch; print(f'PyTorch: {torch.__version__}, GPU: {torch.cuda.device_count()}')"

conda activate tf-dev  
python -c "import tensorflow as tf; print(f'TensorFlow: {tf.__version__}, GPU: {len(tf.config.list_physical_devices(\"GPU\"))}')"

echo -e "\n4. 성능 테스트..."
python performance_benchmark.py

echo -e "\n AI 개발환경 구축 완료!"
echo "이제 본격적인 AI 프로젝트를 시작할 수 있습니다."

7. 제조업 품질검사 AI 모델 실습

구축된 개발환경에서 실제 제조업 품질검사 AI 모델을 살짝 개발해봅니다.

사전 훈련된 EfficientNet 모델을 선정하고, 간단한 제품 이미지 데이터셋으로 파인튜닝을 수행합니다. 품질 등급을 5단계(우수/양호/경미불량/심각불량/폐기)로 분류하는 실용적인 모델을 구현하며, 듀얼 GPU 환경에서의 훈련 성능도 확인합니다. 이 과정을 통해 개발환경이 실제 AI 프로젝트에서 어떻게 활용되는지 체험하며, 완료 후에는 실시간 품질 판정이 가능한 AI 모델을 얻게 됩니다. 예상 소요시간은 약 2시간 정도입니다.

품질검사 모델 선정 및 이해

제조업 품질검사에서는 실시간 처리 속도와 높은 정확도가 모두 중요합니다.

수백 장의 제품 이미지를 빠르게 분석하면서도 불량품을 놓치지 않아야 하기 때문입니다. 이러한 요구사항을 만족하는 모델로 EfficientNet-B3을 선택했습니다. EfficientNet은 Google에서 개발한 모델로, 정확도와 효율성의 균형이 뛰어나며 모바일 환경에서도 동작할 수 있을 정도로 최적화되어 있습니다.

특히 ImageNet에서 사전 훈련된 가중치를 활용하면 적은 데이터로도 높은 성능을 달성할 수 있어 제조업 환경에 적합합니다. 우리의 RTX 4090 듀얼 GPU 환경에서는 EfficientNet-B3 모델을 사용하여 배치 크기 64로 실시간 추론이 가능하며, 한 장당 10ms 이내의 빠른 분석 속도를 제공합니다.

 

선택한 모델의 특징

  • 모델명: EfficientNet-B3
  • 입력 크기: 300×300 픽셀 (품질검사에 충분한 해상도)
  • 파라미터 수: 약 12M개 (적당한 크기로 빠른 추론 가능)
  • 사전 훈련: ImageNet (일반적인 객체 인식 능력 보유)
  • 추론 속도: RTX 4090에서 배치 64 기준 약 50ms

품질 분류 체계

제품 이미지 입력
        ↓
EfficientNet-B3 특징 추출
        ↓
5개 클래스 분류
        ↓
┌────────────────────────────────────┐
│ 우수(0): 완벽한 제품 (신뢰도 > 95%)     │
│ 양호(1): 사용 가능 (신뢰도 85-95%)      │
│ 경미불량(2): 재작업 필요 (신뢰도 70-85%)  │
│ 심각불량(3): 수리 필요 (신뢰도 50-70%)   │
│ 폐기(4): 사용 불가 (신뢰도 < 50%)       │
└────────────────────────────────────┘

사전 훈련된 모델 테스트

실제 데이터로 훈련하기 전에 사전 훈련된 EfficientNet-B3 모델이 우리 시스템에서 정상적으로 작동하는지 확인해보겠습니다. 이 단계에서는 ImageNet으로 훈련된 기본 모델을 로드하고, 간단한 이미지 분류 테스트를 수행합니다.

# model_test.py - 기본 모델 테스트
import torch
import torchvision.models as models
import torchvision.transforms as transforms
from PIL import Image
import time
import numpy as np

def test_efficientnet_model():
    """EfficientNet-B3 모델 기본 동작 테스트"""
    print("=== EfficientNet-B3 모델 테스트 ===")
    
    # 모델 로드 (ImageNet 사전 훈련 가중치)
    model = models.efficientnet_b3(pretrained=True)
    model.eval()
    
    # GPU로 이동
    device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
    model = model.to(device)
    print(f"모델을 {device}로 이동 완료")
    
    # 이미지 전처리 파이프라인
    transform = transforms.Compose([
        transforms.Resize((300, 300)),  # EfficientNet-B3 입력 크기
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], 
                           std=[0.229, 0.224, 0.225])
    ])
    
    # 더미 이미지로 테스트 (실제로는 제품 이미지 사용)
    dummy_image = Image.new('RGB', (800, 600), color='red')
    input_tensor = transform(dummy_image).unsqueeze(0).to(device)
    
    # 추론 속도 테스트
    print("추론 속도 테스트 중...")
    with torch.no_grad():
        # 워밍업
        for _ in range(10):
            _ = model(input_tensor)
        
        # 실제 측정
        start_time = time.time()
        for _ in range(100):
            output = model(input_tensor)
        torch.cuda.synchronize()
        end_time = time.time()
        
        avg_time = (end_time - start_time) / 100
        print(f"단일 이미지 추론 시간: {avg_time*1000:.2f}ms")
        print(f"초당 처리 가능 이미지: {1/avg_time:.1f}장")
    
    return model, transform

# 모델 테스트 실행
model, transform = test_efficientnet_model()

 

듀얼 GPU 배치 처리 테스트

def test_batch_processing():
    """배치 처리 성능 테스트"""
    print("\n=== 배치 처리 성능 테스트 ===")
    
    # 듀얼 GPU DataParallel 설정
    if torch.cuda.device_count() >= 2:
        model_parallel = torch.nn.DataParallel(model, device_ids=[0, 1])
        print("듀얼 GPU DataParallel 활성화")
    else:
        model_parallel = model
        print("단일 GPU 사용")
    
    batch_sizes = [16, 32, 64, 128]
    
    for batch_size in batch_sizes:
        try:
            # 배치 데이터 생성
            batch_input = torch.randn(batch_size, 3, 300, 300, device='cuda:0')
            
            with torch.no_grad():
                start_time = time.time()
                output = model_parallel(batch_input)
                torch.cuda.synchronize()
                end_time = time.time()
                
                batch_time = end_time - start_time
                per_image_time = batch_time / batch_size
                throughput = batch_size / batch_time
                
                print(f"배치 크기 {batch_size:3d}: {batch_time:.3f}s "
                      f"(이미지당 {per_image_time*1000:.1f}ms, "
                      f"처리량 {throughput:.1f} images/sec)")
                
        except RuntimeError as e:
            if "out of memory" in str(e):
                print(f"배치 크기 {batch_size}: GPU 메모리 부족")
                break
            else:
                raise e

test_batch_processing()

7.3 제품 품질 데이터셋 준비

실제 제조업 환경에서는 수천 장의 제품 이미지가 필요하지만, 실습에서는 공개 데이터셋을 활용하여 품질검사 시나리오를 시뮬레이션합니다.

MVTec AD(Anomaly Detection) 데이터셋을 사용하여 정상 제품과 불량 제품을 구분하는 모델을 훈련해보겠습니다.

 

데이터 구성 계획

품질검사 데이터셋 구조:
├── excellent/     (500장) - 완벽한 제품
├── good/         (400장) - 정상 제품
├── minor_defect/ (300장) - 경미한 불량
├── major_defect/ (200장) - 심각한 불량
└── reject/       (100장) - 폐기 대상

총 1,500장 → 증강 후 4,500장
훈련:검증:테스트 = 70:20:10
 
# data_preparation.py - 데이터셋 준비
import os
import shutil
from pathlib import Path
import random
from sklearn.model_selection import train_test_split
import pandas as pd

def prepare_quality_dataset():
    """품질검사 데이터셋 준비"""
    print("=== 품질검사 데이터셋 준비 ===")
    
    # 작업 디렉토리 생성
    data_dir = Path("/workspace/quality_dataset")
    data_dir.mkdir(exist_ok=True)
    
    # 클래스별 디렉토리 생성
    classes = ['excellent', 'good', 'minor_defect', 'major_defect', 'reject']
    for class_name in classes:
        (data_dir / class_name).mkdir(exist_ok=True)
    
    print(f"데이터셋 디렉토리 생성 완료: {data_dir}")
    
    # 실습용 더미 데이터 생성 (실제 환경에서는 실제 제품 이미지 사용)
    print("실습용 샘플 이미지 생성 중...")
    
    from PIL import Image, ImageDraw
    import numpy as np
    
    def create_sample_images(class_name, count):
        """클래스별 샘플 이미지 생성"""
        for i in range(count):
            # 기본 제품 이미지 생성
            img = Image.new('RGB', (300, 300), color='lightgray')
            draw = ImageDraw.Draw(img)
            
            # 제품 외형 그리기
            draw.rectangle([50, 50, 250, 250], fill='white', outline='black', width=2)
            
            # 클래스별 특징 추가
            if class_name == 'excellent':
                # 완벽한 제품 - 추가 특징 없음
                pass
            elif class_name == 'good':
                # 정상 제품 - 미세한 변화
                draw.ellipse([100, 100, 120, 120], fill='lightblue')
            elif class_name == 'minor_defect':
                # 경미한 불량 - 작은 점
                draw.ellipse([150, 150, 160, 160], fill='yellow')
            elif class_name == 'major_defect':
                # 심각한 불량 - 큰 얼룩
                draw.ellipse([120, 120, 180, 180], fill='orange')
            elif class_name == 'reject':
                # 폐기 대상 - 심각한 손상
                draw.line([50, 50, 250, 250], fill='red', width=5)
                draw.line([50, 250, 250, 50], fill='red', width=5)
            
            # 이미지 저장
            img_path = data_dir / class_name / f"{class_name}_{i:03d}.jpg"
            img.save(img_path, 'JPEG')
    
    # 클래스별 이미지 생성
    image_counts = {'excellent': 100, 'good': 80, 'minor_defect': 60, 
                   'major_defect': 40, 'reject': 20}
    
    for class_name, count in image_counts.items():
        create_sample_images(class_name, count)
        print(f"{class_name}: {count}장 생성 완료")
    
    print("데이터셋 준비 완료!")
    return data_dir

# 데이터셋 준비 실행
dataset_path = prepare_quality_dataset()

7.4 품질검사 모델 훈련

이제 준비된 데이터셋으로 EfficientNet-B3 모델을 파인튜닝하여 품질검사 전용 모델을 만들어보겠습니다.

전이학습(Transfer Learning)을 활용하여 ImageNet에서 학습된 특징을 우리의 품질검사 작업에 맞게 조정합니다.

품질검사 모델 훈련 코드 예시 >
# quality_trainer.py - 품질검사 모델 훈련
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
import torchvision.transforms as transforms
from PIL import Image
import os
from pathlib import Path
import time

class QualityDataset(Dataset):
    """품질검사 데이터셋 클래스"""
    
    def __init__(self, data_dir, transform=None):
        self.data_dir = Path(data_dir)
        self.transform = transform
        self.classes = ['excellent', 'good', 'minor_defect', 'major_defect', 'reject']
        self.class_to_idx = {cls: idx for idx, cls in enumerate(self.classes)}
        
        # 이미지 파일 목록 생성
        self.samples = []
        for class_name in self.classes:
            class_dir = self.data_dir / class_name
            if class_dir.exists():
                for img_file in class_dir.glob("*.jpg"):
                    self.samples.append((str(img_file), self.class_to_idx[class_name]))
        
        print(f"데이터셋 로드 완료: {len(self.samples)}개 이미지")
    
    def __len__(self):
        return len(self.samples)
    
    def __getitem__(self, idx):
        img_path, label = self.samples[idx]
        image = Image.open(img_path).convert('RGB')
        
        if self.transform:
            image = self.transform(image)
        
        return image, label

def create_quality_model(num_classes=5):
    """품질검사용 모델 생성"""
    # EfficientNet-B3 사전 훈련 모델 로드
    model = models.efficientnet_b3(pretrained=True)
    
    # 분류기 교체 (5개 품질 등급)
    model.classifier = nn.Sequential(
        nn.Dropout(0.3),
        nn.Linear(model.classifier[1].in_features, 512),
        nn.ReLU(),
        nn.Dropout(0.2),
        nn.Linear(512, num_classes)
    )
    
    return model

def train_quality_model():
    """품질검사 모델 훈련"""
    print("=== 품질검사 모델 훈련 시작 ===")
    
    # 데이터 변환 설정
    train_transform = transforms.Compose([
        transforms.Resize((320, 320)),
        transforms.RandomCrop((300, 300)),
        transforms.RandomHorizontalFlip(p=0.5),
        transforms.RandomRotation(10),
        transforms.ColorJitter(brightness=0.2, contrast=0.2),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], 
                           std=[0.229, 0.224, 0.225])
    ])
    
    # 데이터셋 및 데이터로더 생성
    dataset = QualityDataset("/workspace/quality_dataset", transform=train_transform)
    dataloader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=4)
    
    # 모델 생성 및 GPU 이동
    model = create_quality_model()
    device = torch.device('cuda:0')
    model = model.to(device)
    
    # 듀얼 GPU 사용 (가능한 경우)
    if torch.cuda.device_count() >= 2:
        model = nn.DataParallel(model, device_ids=[0, 1])
        print("듀얼 GPU DataParallel 활성화")
    
    # 손실 함수 및 옵티마이저
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)
    scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)
    
    # 훈련 루프
    model.train()
    epochs = 20
    
    print(f"훈련 시작: {epochs} 에포크, 배치 크기 32")
    start_time = time.time()
    
    for epoch in range(epochs):
        epoch_loss = 0.0
        correct = 0
        total = 0
        
        for batch_idx, (images, labels) in enumerate(dataloader):
            images, labels = images.to(device), labels.to(device)
            
            # Forward pass
            optimizer.zero_grad()
            outputs = model(images)
            loss = criterion(outputs, labels)
            
            # Backward pass
            loss.backward()
            optimizer.step()
            
            # 통계 계산
            epoch_loss += loss.item()
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
            
            if batch_idx % 5 == 0:
                print(f"에포크 {epoch+1}/{epochs}, 배치 {batch_idx+1}/{len(dataloader)}, "
                      f"손실: {loss.item():.4f}")
        
        # 에포크 결과
        accuracy = 100 * correct / total
        avg_loss = epoch_loss / len(dataloader)
        
        print(f"에포크 {epoch+1} 완료 - 손실: {avg_loss:.4f}, 정확도: {accuracy:.2f}%")
        scheduler.step()
    
    total_time = time.time() - start_time
    print(f"훈련 완료! 총 소요시간: {total_time/60:.1f}분")
    
    # 모델 저장
    model_save_path = "/workspace/quality_model.pth"
    if isinstance(model, nn.DataParallel):
        torch.save(model.module.state_dict(), model_save_path)
    else:
        torch.save(model.state_dict(), model_save_path)
    
    print(f"모델 저장 완료: {model_save_path}")
    return model

# 모델 훈련 실행
trained_model = train_quality_model()

7.5 모델 성능 평가 및 테스트

훈련된 모델의 성능을 평가하고 실제 사용 가능한 수준인지 검증해보겠습니다.

 

모델 성능 평가 및 테스트를 위한 코드 예시 >
# model_evaluation.py - 모델 성능 평가
def evaluate_quality_model():
    """훈련된 품질검사 모델 평가"""
    print("=== 모델 성능 평가 ===")
    
    # 훈련된 모델 로드
    model = create_quality_model()
    model.load_state_dict(torch.load("/workspace/quality_model.pth"))
    model = model.to(device)
    model.eval()
    
    # 테스트 변환
    test_transform = transforms.Compose([
        transforms.Resize((300, 300)),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], 
                           std=[0.229, 0.224, 0.225])
    ])
    
    # 클래스별 테스트
    classes = ['excellent', 'good', 'minor_defect', 'major_defect', 'reject']
    class_accuracies = {}
    
    with torch.no_grad():
        for class_idx, class_name in enumerate(classes):
            class_dir = Path(f"/workspace/quality_dataset/{class_name}")
            correct = 0
            total = 0
            
            for img_file in class_dir.glob("*.jpg"):
                # 이미지 로드 및 전처리
                image = Image.open(img_file).convert('RGB')
                input_tensor = test_transform(image).unsqueeze(0).to(device)
                
                # 예측
                output = model(input_tensor)
                predicted = torch.argmax(output, dim=1).item()
                
                if predicted == class_idx:
                    correct += 1
                total += 1
            
            accuracy = (correct / total) * 100 if total > 0 else 0
            class_accuracies[class_name] = accuracy
            print(f"{class_name}: {correct}/{total} = {accuracy:.1f}%")
    
    # 전체 정확도
    overall_accuracy = sum(class_accuracies.values()) / len(class_accuracies)
    print(f"\n전체 평균 정확도: {overall_accuracy:.1f}%")
    
    return class_accuracies

# 실시간 추론 테스트
def test_realtime_inference():
    """실시간 추론 성능 테스트"""
    print("\n=== 실시간 추론 테스트 ===")
    
    # 모델을 추론 모드로 설정
    model = create_quality_model()
    model.load_state_dict(torch.load("/workspace/quality_model.pth"))
    model = model.to(device)
    model.eval()
    
    # 더미 이미지로 추론 속도 측정
    dummy_input = torch.randn(1, 3, 300, 300, device=device)
    
    # 워밍업
    with torch.no_grad():
        for _ in range(10):
            _ = model(dummy_input)
    
    # 실제 측정
    start_time = time.time()
    with torch.no_grad():
        for _ in range(1000):
            output = model(dummy_input)
            prediction = torch.argmax(output, dim=1)
    
    torch.cuda.synchronize()
    end_time = time.time()
    
    avg_time = (end_time - start_time) / 1000
    fps = 1 / avg_time
    
    print(f"추론 시간: {avg_time*1000:.2f}ms")
    print(f"처리 속도: {fps:.1f} FPS")
    print(f"실시간 처리 가능: {'✅' if fps >= 30 else '❌'}")

# 평가 실행
accuracies = evaluate_quality_model()
test_realtime_inference()

 

예상 결과

  • 전체 정확도: 85% 이상
  • 추론 속도: 10ms 미만 (100+ FPS)
  • 메모리 사용량: GPU당 2GB 미만
  • 실시간 처리: 가능

 

마무리

이제 제조업 로컬AI 구축을 위한 인프라 도입 및 개발 환경 설정을 완료했습니다. 개발환경 설정의 검증을 위해 반드시 작은 프로젝트를 생성해서 간단하게라도 돌려보셔야 합니다. 커다란 AI모델에서는 인프라의 안정성을 검증하는게 복합하고 모호할 수 있습니다

 

 RTX 4090 듀얼 GPU와 Threadripper CPU로 구성된 이 시스템은 GPT-2 규모의 모델 훈련부터 실시간 추론 서비스까지 모든 AI 프로젝트를 지원할 수 있습니다. PyTorch와 TensorFlow 모두 멀티 GPU를 완벽하게 활용하며, Docker 컨테이너 환경에서 일관된 개발 경험을 제공합니다. 이는 단순한 학습 환경이 아닌, 실제 제품 개발에 바로 투입할 수 있는 프로덕션 수준의 인프라입니다.

 

구축된 환경의 진정한 가치는 앞으로의 프로젝트에서 드러날 것입니다. 데이터 전처리부터 모델 훈련, 배포까지의 전체 파이프라인이 이 환경에서 원활하게 실행되며, 특히 멀티 GPU 환경은 개발 속도를 획기적으로 향상시킬 것입니다. 중요한 것은 이 환경을 지속적으로 관리하고 최적화하는 것입니다. 정기적인 드라이버 업데이트, 프레임워크 버전 관리, 그리고 성능 모니터링을 통해 항상 최적의 상태를 유지하시기 바랍니다. 이제 여러분은 어떤 AI 도전과제든 자신있게 맞서할 수 있는 강력한 개발 기반을 갖추게 되었습니다.


FAQ

Q1: 듀얼 GPU가 제대로 활용되지 않는 것 같습니다.
A: nvidia-smi로 GPU 사용률을 실시간 모니터링해보세요. PyTorch에서는 DataParallel이나 DistributedDataParallel을 명시적으로 사용해야 하며, 배치 크기가 충분히 커야 두 GPU가 모두 활용됩니다. 단일 GPU로 처리 가능한 작은 모델의 경우 자동으로 멀티 GPU를 사용하지 않을 수 있습니다.

 

Q2: CUDA 메모리 부족 오류가 발생합니다.
A: 24GB GPU에서도 메모리 부족이 발생한다면 배치 크기를 줄여보세요. torch.cuda.empty_cache()로 사용하지 않는 메모리를 정리하고, 그래디언트 누적이나 체크포인팅을 활용하여 메모리 사용량을 최적화할 수 있습니다.

 

Q3: Docker 컨테이너에서 GPU 성능이 느려집니다.
A: Docker 컨테이너의 GPU 성능은 호스트와 거의 동일해야 합니다. 성능 차이가 크다면 --gpus all 옵션 사용, 적절한 CUDA 이미지 선택, 메모리 제한 설정을 확인해보세요.

 

Q4: 시스템 온도가 너무 높습니다.
A: RTX 4090 듀얼 구성은 발열이 큽니다. 케이스 팬 추가, GPU 파워 리미트 조정(nvidia-smi -pl 350), 언더볼팅을 고려해보세요. 지속적으로 80도 이상이면 성능 제한이나 하드웨어 손상 위험이 있습니다.

 

Q5: 가상환경 전환이 번거롭습니다.
A: Jupyter Lab에서 커널을 여러 개 등록하면 하나의 인터페이스에서 다양한 환경을 사용할 수 있습니다. python -m ipykernel install --user --name env-name 명령어로 각 conda 환경을 커널로 등록하세요.


참조문헌

  1. NVIDIA Corporation. "CUDA Installation Guide for Linux". NVIDIA Developer Documentation, 2024.
  2. AMD. "Threadripper PRO Optimization Guide". AMD Developer Resources, 2024.
  3. PyTorch Team. "Multi-GPU Training Best Practices". PyTorch Documentation, 2024.
  4. TensorFlow Team. "Distributed Training with Multiple GPUs". TensorFlow Guide, 2024.
  5. Docker Inc. "NVIDIA Container Toolkit User Guide". Docker Documentation, 2024.
  6. Conda Community. "Managing Environments". Conda Documentation, 2024.