Optimasi kompilasi untuk High-Performance Computing (HPC) bergantung pada pemanfaatan vektorisasi SIMD (Single Instruction, Multiple Data) seperti AVX2 dan AVX-512. Masalah umum dalam siklus pengembangan adalah terjadinya regresi performa throughput atau penurunan IPC (Instructions Per Cycle) akibat restrukturisasi kode atau pemilihan flag target arsitektur yang tidak tepat. Artikel ini membahas penerapan CI matrix profiling HPC: optimasi flag kompiler SIMD menggunakan GitHub Actions, profiling level instruksi dengan linux-perf, isolasi hardware dari noisy neighbor, dan integrasi threshold gating otomatis sebelum penggabungan kode (merge).

Arsitektur CI Matrix untuk SIMD Target

Untuk memvalidasi throughput kompilasi pada beberapa set instruksi secara paralel, kita memanfaatkan matrix build. Setiap runner menguji kombinasi flag arsitektur mikro untuk GCC/Clang (C++) dan rustc (Rust).

# .github/workflows/hpc-matrix-bench.yml
name: HPC SIMD Profiling Matrix

on:
  pull_request:
    branches: [ main ]

jobs:
  simd-profile:
    runs-on: [self-hosted, linux, x64, baremetal]
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: "AVX2 Baseline"
            cxxflags: "-O3 -march=haswell -mavx2 -mfma"
            rustflags: "-C target-cpu=haswell -C target-feature=+avx2,+fma"
            target: "avx2"
            threshold_ipc: 1.8
          - name: "AVX-512 Skylake-X"
            cxxflags: "-O3 -march=skylake-avx512 -mavx512f -mavx512dq -mavx512cd -mavx512bw -mavx512vl"
            rustflags: "-C opt-level=3 -C target-cpu=skylake-avx512"
            target: "avx512"
            threshold_ipc: 2.2
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Setup System & Mitigate Noise
        run: |
          sudo cpupower frequency-set --governor performance
          echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
          echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid

      - name: Build Benchmarks
        env:
          CXXFLAGS: ${{ matrix.cxxflags }}
          RUSTFLAGS: ${{ matrix.rustflags }}
        run: |
          make clean && make bench-simd

      - name: Profile via Perf and Gate Regressions
        run: |
          taskset -c 2 ./ci/run_profile.sh ${{ matrix.target }} ${{ matrix.threshold_ipc }}

Mitigasi Noisy Neighbor pada Bare-Metal Runner

Virtual runner publik (seperti runner standar GitHub Actions) rentan terhadap multi-tenant core contention, virtualisasi hypervisor, dan throttling termal yang mendistorsi benchmarking. Runner bare-metal mandiri (self-hosted) direkomendasikan dengan langkah isolasi berikut:

  • CPU Governor Locking: Mengunci scaling governor ke mode performance untuk mencegah latency penyesuaian frekuensi P-state.
  • Core Pinning (Affinity): Menggunakan taskset atau cset shield untuk memisahkan core eksekusi benchmark dari thread OS dan background runner agent.
  • Address Space Layout Randomization (ASLR): Menonaktifkan ASLR sementara (randomize_va_space = 0) untuk mengurangi variasi cache hit/miss akibat relokasi memori.
  • Prefetcher Consistency: Memastikan status hardware prefetcher konsisten melalui register MSR jika diperlukan.

Script Profiling Instruksi dan Memory Bandwidth

Pengujian throughput HPC mengukur efisiensi metrik TOP500/ISC: meminimalkan memory stall dan memaksimalkan densitas komputasi vektor. Script berikut menjalankan binary di bawah isolasi taskset, mengekstrak metrik hardware performance counters (PMU), dan melakukan perbandingan throughput eksekusi.

#!/usr/bin/env bash
# ci/run_profile.sh
set -euo pipefail

TARGET="$1"
THRESHOLD_IPC="$2"
BINARY="./build/bin/simd_kernel_${TARGET}"
LOG_FILE="perf_${TARGET}.log"

# Eksekusi perf stat dengan hardware counters spesifik
perf stat -e \
  instructions,\
  cycles,\
  fp_arith_inst_retired.512b_packed_single,\
  fp_arith_inst_retired.256b_packed_single,\
  mem_load_retired.l3_miss,\
  llc_misses.mem_read \
  -o "${LOG_FILE}" -- "${BINARY}"

cat "${LOG_FILE}"

# Ekstraksi cycles dan instructions untuk kalkulasi IPC
INSTR=$(grep "instructions" "${LOG_FILE}" | awk '{print $1}' | tr -d ',')
CYCLES=$(grep "cycles" "${LOG_FILE}" | awk '{print $1}' | tr -d ',')

if [ -z "$CYCLES" ] || [ "$CYCLES" -eq 0 ]; then
  echo "Error: Invalid PMU data collected."
  exit 1
fi

IPC=$(awk -v inst="$INSTR" -v cyc="$CYCLES" 'BEGIN {printf "%.2f", inst/cyc}')
echo "Captured IPC: ${IPC} (Threshold: ${THRESHOLD_IPC})"

# Evaluasi threshold IPC (Awk comparison)
STATUS=$(awk -v ipc="$IPC" -v th="$THRESHOLD_IPC" 'BEGIN {print (ipc >= th) ? 1 : 0}')

if [ "$STATUS" -eq 0 ]; then
  echo "[REGRESI TERDETEKSI] IPC target ${TARGET} turun di bawah batas minimum: ${IPC} < ${THRESHOLD_IPC}"
  exit 1
fi

echo "[PASSED] Throughput target ${TARGET} memenuhi batas toleransi."

Penyebab Regresi SIMD dan Verifikasi LLVM IR

Regresi performa pada flag AVX-512 sering kali terjadi bukan karena instruksi tidak terpasang, melainkan efek samping mikroarsitektur:

  • Downclocking Frekuensi Turbo: Menjalankan instruksi 512-bit berat (seperti FMA3) pada inti lama (Skylake-X) dapat memicu transisi lisensi voltase prosesor, menurunkan frekuensi base seluruh inti CPU. Profiling memvalidasi apakah AVX-512 memberikan speedup nyata dibandingkan AVX2.
  • Vector Register Spilling: Kurangnya register alokasi dapat memicu transfer register SIMD ke stack (L1/L2 cache), meningkatkan beban memory bus secara drastis.
  • Alignment Stalls: Pemuatan data tak selaras (unaligned loads) menghambat operasi 512-bit vector pack. Selalu gunakan alignas(64) untuk buffer AVX-512 atau alignas(32) untuk AVX2.

Integrasikan inspeksi intermediate representation (IR) pada pipeline CI jika compiler gagal melakukan autovektorisasi menggunakan flag -Rpass=loop-vectorize -Rpass-missed=loop-vectorize -Rpass-analysis=loop-vectorize pada Clang.

Threshold Gating Otomatis pada Pull Request

Integrasi threshold gating memastikan binary yang gagal mencapai target komputasi langsung diblokir sebelum masuk ke tahap integrasi deployment cluster. Pipeline CI menghentikan eksekusi status checks (non-zero exit code) jika IPC turun atau jika cache miss L3 melebihi persentase yang ditoleransi. Mekanisme ini membatasi degradasi performa HPC di lingkungan produksi sejak tahap code review.