DPAS 실습 가이드

NVMe I/O Completion 모드별 성능 비교 실습

2026-1 시스템최신기술
English

사전 준비

플랫폼별 QEMU 설치 및 Ubuntu VM 구축이 완료된 상태여야 합니다.

필수 환경 Ubuntu 22.04 VM + mainline 커널 5.18 (uname -r5.18.0-051800-generic)
왜 커널 5.18인가? 이 실습에서는 preadv2(RWF_HIPRI)를 통한 동기식 Direct I/O polling을 사용합니다. 이 기능은 Linux 커널 5.19부터 제거되었기 때문에, 5.18이 이 기능을 지원하는 마지막 커널입니다. QEMU Guest VM 안에서 커널 5.18을 사용하므로, 호스트 OS의 커널 버전과는 무관하게 polling 실습이 가능합니다.

I/O Completion 배경 읽기 자료 → — Interrupt/Polling의 역사, FAST '26 최신 연구, io_uring과 polling의 미래

Part 1: DPAS 커널 설치

제공된 deb 패키지로 DPAS 패치가 적용된 커널을 설치합니다.

deb 패키지란? .deb 파일은 Ubuntu/Debian 계열 Linux에서 사용하는 소프트웨어 설치 패키지입니다. Windows의 .msi 설치 파일, macOS의 .pkg와 같은 역할입니다. sudo dpkg -i 파일.deb 명령으로 설치하며, 커널 이미지·헤더 등 시스템 파일을 자동으로 올바른 위치에 배치해 줍니다.
아키텍처 선택 — 호스트 OS가 아닌 CPU 아키텍처 기준 커널 패키지는 호스트 운영체제(macOS/Windows/Linux)와 무관하게, VM이 실행되는 CPU 아키텍처에 따라 선택합니다. Guest VM 안에서 uname -m을 실행하면 아키텍처를 확인할 수 있습니다.
호스트 환경uname -m 결과필요한 패키지
Apple Silicon Mac (M1/M2/M3/M4)aarch64ARM64
Intel Mac / Linux PC / Windows (WSL2)x86_64x86_64

커널 패키지 다운로드

VM의 CPU 아키텍처에 맞는 패키지를 다운로드하세요.

ARM64 커널 이미지 (23MB) ARM64 헤더 (8MB)
x86_64 커널 이미지 (12MB) x86_64 헤더 (8MB)

1-1. 패키지 전송

다운로드한 deb 파일을 호스트에서 VM으로 전송합니다.

# 호스트 터미널에서 실행
scp -P 2222 linux-image-5.18.0-dpas_*.deb <username>@localhost:~/
scp -P 2222 linux-headers-5.18.0-dpas_*.deb <username>@localhost:~/

1-2. 설치 및 재부팅

# VM 내부에서 실행
sudo dpkg -i ~/linux-image-5.18.0-dpas_*.deb ~/linux-headers-5.18.0-dpas_*.deb
sudo reboot

1-3. 설치 확인

uname -r
# 5.18.0-dpas
부팅 커널이 변경되지 않은 경우 GRUB이 이전 커널로 부팅할 수 있습니다. 아래 명령으로 DPAS 커널을 선택 후 재부팅하세요:
sudo grub-reboot "Advanced options for Ubuntu>Ubuntu, with Linux 5.18.0-dpas"
sudo reboot

Part 2: 실습 — 모드별 성능 비교

2-1. 벤치마크 스크립트

통합 벤치마크 스크립트 bench.sh를 사용합니다. 4개 모드(INT/CP/PAS/DPAS) × 5개 job 수(1,2,4,8,16)를 자동으로 실행합니다.

bench.sh 다운로드

주요 특징

사용법

# VM으로 전송
scp -P 2222 bench.sh <username>@localhost:~/

# VM 내부에서 실행
chmod +x bench.sh
sudo bash bench.sh

2-2. 결과 기록

스크립트 출력의 IOPS를 아래 표에 기록합니다.

Modej=1j=2j=4j=8j=16
INT
CP
PAS
DPAS

2-3. DPAS mode transition 확인

bench.sh 실행 결과의 DPAS breakdown에서 모드 전환을 확인합니다:

MODE 값의미
0INT (Interrupt)
1CP (Continuous Polling)
2PAS (초기 상태)
3OL (Overloaded)

기대 동작

Jobs기대 최종 모드이유
1CP (MODE 1)QD=1 → PAS→CP 전환, polling으로 최저 latency
2+INT (MODE 0)QD>1 → PAS→OL→INT 전환, 인터럽트로 CPU 양보

2-4. 분석 질문

  1. INT와 CP 모드에서 j=1일 때 IOPS 차이의 원인은 무엇인가?
  2. CP 모드에서 job 수를 늘려도 IOPS가 크게 증가하지 않는 이유는? (CPU 사용률 관점)
  3. DPAS가 j=1에서 CP에 근접하고, j≥4에서 INT에 근접하는 이유를 mode transition 관점에서 설명하시오.
  4. switch_stat의 DPAS breakdown에서 pas io 수가 polled io보다 항상 적은 이유는?
  5. d_init 값이 DPAS 모드 전환에 미치는 영향을 설명하시오.

Part 3: DPAS 커널 내부 구조

3-0. IO 경로와 DPAS 개입 지점

fio가 IO를 제출하면 커널 block layer를 거쳐 NVMe 드라이버에 도달합니다. DPAS는 polling 경로에서 completion 대기 방식을 제어합니다.

/* Userspace */
fio (pvsync2 --hipri)
  └─ preadv2(RWF_HIPRI)                   /* polling 요청 플래그 */

/* Kernel: IO 제출 (block/fops.c) */
  └─ blk_mq_submit_bio()                  /* block layer 진입 */
       ├─ ★ INT→OL 전환 (int_cnt ≥ 10000)  /* 제출 경로에서 재평가 */
       └─ nvme_queue_rq()                   /* NVMe 드라이버로 전달 */

/* Kernel: IO 완료 대기 (block/blk-mq.c) */
  └─ blk_mq_poll()                        /* polling 진입점 */
       └─ blk_mq_poll_hybrid()             /* ★ DPAS 핵심: 모드 판단 */
            ├─ blk_mq_poll_pas_nsecs()      /* adaptive sleep 계산 (dur, tf) */
            ├─ mode transition logic         /* CP↔PAS→OL→INT 전환 */
            └─ hrtimer_nanosleep()           /* PAS: sleep 후 poll */
               또는 즉시 poll (CP)
               또는 return → interrupt 대기 (INT)
소스 코드 위치 모드 전환 로직은 두 곳에 분산되어 있습니다: block/blk-mq.c의 polling 경로 (CP↔PAS→OL→INT)와 block/fops.c의 제출 경로 (INT→OL 재평가).

sysfs 인터페이스

DPAS 커널은 /sys/block/nvme0n1/queue/ 아래에 다음 파라미터를 제공합니다.

파라미터설명기본값
switch_enabledDPAS mode switching 활성화0
switch_statCPU별 모드 통계 출력 (읽기 전용)
pas_enabledPAS 모드 활성화0
pas_adaptive_enabledAdaptive sleep 활성화0
switch_param1PAS→OL 임계치 (tf > param1). 논문 설정: 00
switch_param2OL→PAS 임계치 (avg QD ≤ param2)10
switch_param3OL→INT 임계치 (avg QD > param3)10
switch_param4PAS→CP 전환 활성화 (0/1)1
pas_d_initAdaptive sleep 초기값 및 최소값 (ns). bench.sh는 avg_lat/10으로 자동 설정100
QD 10x multiplier QD 관련 파라미터는 10배 스케일을 사용합니다. param2=10은 average QD ≤ 1.0을 의미합니다. 이는 정수 연산으로 소수점 정밀도를 확보하기 위한 설계입니다.

3-1. DPAS 모드 전이 다이어그램

CP Polling PAS Sleep+Poll OL Overloaded INT Interrupt 초기 모드 cp_cnt ≥ 1000 param4≥1 && avg_qd = 1.0 tf > param1 avg_qd ≤ param2 avg_qd > param3 int_cnt ≥ 10000 전환 조건 부하 증가 방향 부하 감소 방향 재평가 (INT→OL) 초기 전환 (CP→PAS)

tf (timer failure): adaptive sleep의 durd_init 바닥에 닿을 때 증가. QD가 높아 sleep이 계속 줄어들면 tf가 쌓여 PAS→OL 전환이 발생합니다.

3-2. 핵심 제어 로직 (block/blk-mq.c)

아래 코드는 blk_mq_poll_hybrid() 내부의 DPAS 모드 전환 로직입니다. sysfs 파라미터가 실제로 어떻게 사용되는지 확인하세요.

① PAS 평가 (100 IO마다)

/* PAS 모드에서 100개 IO를 수집하면 평가 */
if(sc->mode == _PAS && sc->pas_cnt >= 100) {
    average_qd = sc->qd_sum * 10 / sc->pas_cnt;  /* 10x 정밀도 */

    if(sc->param4 >= 1 && average_qd == 10) {  /* ← switch_param4: PAS→CP 활성화 */
        sc->mode = _CP;          /* QD=1.0 → polling이 유리 */

    } else if(sc->tf > sc->param1) {            /* ← switch_param1: PAS→OL 임계치 */
        sc->mode = _OL;          /* timer failure → overloaded */

    } else {                                  /* 유지: PAS에 머무름 */
        sc->pas_cnt = 0;
        sc->qd_sum = 0;
        sc->tf = 0;              /* tf 리셋 (매 평가마다) */
    }
}

② OL 평가 (100 IO마다)

/* OL(Overloaded) 모드에서 100개 IO를 수집하면 평가 */
if(sc->mode == _OL && sc->ol_cnt >= 100) {
    average_qd = sc->qd_sum * 10 / sc->ol_cnt;

    if(average_qd <= sc->param2) {             /* ← switch_param2: OL→PAS 복귀 */
        sc->mode = _PAS;         /* 부하 감소 → sleep 재시도 */

    } else if(average_qd > sc->param3) {       /* ← switch_param3: OL→INT 전환 */
        sc->mode = _INT;         /* 고부하 → interrupt 모드 */

    } else {                                  /* 유지: OL에 머무름 */
        sc->ol_cnt = 0;
        sc->qd_sum = 0;
    }
}

③ Adaptive Sleep & Timer Failure

/* sr_pnlt: 이전 IO가 oversleep(0) / undersleep(1)
   sr_last:  현재 IO가 oversleep(0) / undersleep(1)
   case: sr_pnlt*2 + sr_last → 0,1,2,3 */
cur_case = stat.sr_pnlt * 2 + stat.sr_last;
switch(cur_case) {
    case 0: adj -= dn;                         /* over,over → sleep 감소 */
    case 1: adj = div + up;                     /* over,under → sleep 약간 증가 */
    case 2: adj = div - dn;                     /* under,over → sleep 약간 감소 */
    case 3: adj += up;                          /* under,under → sleep 증가 */
}

stat.dur = stat.dur * adj / div;              /* sleep 시간 업데이트 */

if(stat.dur < q->d_init) {                   /* ← pas_d_init: 최소 sleep */
    stat.dur = q->d_init;                     /* floor clamp */
    sc->tf++;                                 /* timer failure 증가! */
}                                             /* → tf가 쌓이면 PAS→OL 전환 */
핵심 흐름 Adaptive sleep이 dur을 최적화하는데, 부하가 높으면 dur이 계속 줄어 d_init 바닥에 도달 → tf++tf > param1이면 PAS→OL 전환 → QD가 여전히 높으면 OL→INT로 interrupt 모드 전환. 반대로 QD=1이면 PAS→CP로 전환하여 polling으로 최저 latency 달성.

Part 4: 커널 소스 컴파일 도전과제

deb 패키지 대신 직접 커널 소스에 DPAS 패치를 적용하고 빌드합니다.

4-1. 빌드 의존성 설치

sudo apt install -y build-essential libncurses-dev bison flex libssl-dev \
    libelf-dev bc pahole dwarves zstd

4-2. 커널 소스 다운로드

cd ~
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.18.tar.xz
tar xf linux-5.18.tar.xz
cd linux-5.18

4-3. DPAS 패치 적용

# 호스트에서 VM으로 패치 전송 후
patch -p1 < ~/dpas.patch
Makefile hunk 실패 패치가 5.18-rc6 기준이라 Makefile hunk 하나가 실패합니다. 무시해도 됩니다.
대신 localversion을 수동 설정: echo "-dpas" > localversion

4-4. 커널 설정 (최소화)

cp /boot/config-$(uname -r) .config
yes '' | make localmodconfig
왜 localmodconfig? 기본 config로 빌드하면 수천 개 모듈이 포함되어 디스크 부족(No space left on device)이 발생합니다. localmodconfig는 현재 로드된 모듈만 포함하여 빌드 시간과 디스크 사용량을 대폭 줄입니다.

4-5. 빌드

make -j$(nproc) bindeb-pkg

빌드 완료 시 홈 디렉토리에 linux-image-*.deb, linux-headers-*.deb 파일이 생성됩니다.

4-6. 설치

sudo dpkg -i ~/linux-image-5.18.0-dpas_*.deb ~/linux-headers-5.18.0-dpas_*.deb
sudo reboot

트러블슈팅

증상원인해결
No space left on device빌드 산출물이 디스크 초과make clean, tarball 삭제, localmodconfig 사용
Makefile Hunk #1 FAILED패치 버전 차이무시, localversion으로 대체
부팅 후 커널 미변경GRUB 기본 부팅 커널grub-reboot으로 DPAS 커널 선택
다수 hunk 실패이미 패치 적용된 소스에 재적용소스를 다시 풀고 재시도
빌드 15GB+ 필요디스크 여유 부족df -h / 확인, LVM 확장 또는 파일 정리

참고: QEMU 환경의 제약

항목QEMU실제 하드웨어
CP vs INT 비교유효 (1.7-1.8x IOPS 차이)유효
PAS adaptive sleep타이머 부정확, tf 노이즈정확
DPAS mode transition동작, 절대 성능은 참고용기본 파라미터로 동작
Multi-core 스케일링에뮬레이션 오버헤드로 왜곡Linear에 근접
실습 핵심 절대 성능 수치보다 모드 간 상대적 차이와 전환 동작에 집중하세요. I/O completion 메커니즘의 원리를 이해하는 것이 목표입니다.