libargus 1.0.0 – Java 22용 Project Panama를 통한 제로 할당 네이티브 AI 런타임

libargus 1.0.0은 Java 22+를 위한 초저지연 AI 추론을 제공합니다

핵심 요약: libargus 1.0.0은 안정적인 비관리 런타임으로, LLM 텍스트 생성, Whisper 음성‑텍스트 변환, 텍스트‑음성 변환, 그리고 멀티모달(시각/오디오/비디오) 파이프라인을 단일 프로세스‑전체 네이티브 레이어로 통합하고, Project Panama의 Foreign Function & Memory (FFM) 인터페이스를 통해 제로 복사, 포인터‑전용 Java API를 제공합니다. 이 설계는 JVM 힙 할당을 제거하고 VRAM 단편화를 방지하며, CPU 또는 CUDA 가속 GPU에서 스레드‑안전하고 고처리량 추론을 가능하게 합니다.


핵심 아키텍처 보장 사항

  • 프로세스 전역 백엔드 단일성 – 단일 ggml_backend_load_all() 호출로 모든 컴퓨트 백엔드를 한 번 초기화하여 텍스트, 오디오 및 멀티모달 서브시스템 전반에 걸친 드라이버 경쟁 조건과 VRAM 단편화를 방지합니다.
  • 가중치와 실행 컨텍스트 분리 – 모델 가중치(argus_model_t)는 한 번 로드되며 다수의 동시 argus_context_t 세션 간에 공유될 수 있어 메모리 오버헤드를 감소시킵니다.
  • 제로 할당 메모리 경계 – 모든 핫‑패스 데이터(토큰, 오디오 PCM, 비디오 프레임)는 MemorySegment 객체로 직접 네이티브 코드에 전달되어 Java 원시 배열 복사와 GC 압력을 없앱니다.
  • 포인터‑전용 FFM 정렬 – C ABI는 원시 포인터를 받는 평면 함수들만으로 구성되며, 구조체 패딩은 컴파일러 간 레이아웃 안정성을 보장하기 위해 수동으로 패킹됩니다.
  • 선택적 동시성 잠금 – 컨텍스트 수준 뮤텍스가 가변 상태를 보호하고 토크나이저 읽기는 락‑프리로 유지되어 안전한 다중 스레드 사용을 가능하게 합니다.
  • KV‑캐시 양자화 및 추측 초안 – Q4/Q8 캐시 포맷과 다중 토큰 예측(draft‑mtp)에 대한 네이티브 지원이 생성 속도를 높입니다.
  • 비관리 비디오 반복 – 내부 FFmpeg 파이프가 비디오 프레임이나 타임스탬프 청크를 프레임‑단위로 스트리밍하며 중간 Java 객체를 사용하지 않습니다.

코드베이스 레이아웃 (고수준)

libargus/
├─ CMakeLists.txt                # Build isolation & optimization flags
├─ include/libargus.h            # Stable C ABI definitions
├─ src/
│  ├─ argus_common.cc           # Global backend lifecycle
│  ├─ argus_text.cc             # Llama text generation & TTS
│  ├─ argus_audio.cc            # Whisper ASR
│  └─ argus_multimodal.cc       # Vision/audio/video pipelines
└─ bindings/java/
   └─ src/main/java/cc/projectargus/libargus/
      ├─ ArgusBackend.java          # Backend init / teardown
      ├─ ArgusModel.java            # GGUF weight manager (AutoCloseable)
      ├─ ArgusContext.java          # Text generation session
      ├─ ArgusAudioContext.java     # Speech‑to‑text session
      ├─ ArgusMultimodalContext.java# Multimodal projector session
      ├─ ArgusBitmap.java           # Unmanaged RGB/PCM buffer
      ├─ ArgusVideo.java            # Video frame iterator
      └─ internal/…                # Panama struct layouts & native bindings

네이티브 라이브러리 빌드

# Enable CUDA acceleration (optional) and create a Release build
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON
cmake --build build --config Release -j $(nproc)

생성된 공유 객체(libargus.so 또는 argus.dll)는 완전하게 정적으로 링크된 GGML, llama.cpp, 및 libmtmd 엔진을 포함합니다.

관용적인 Java 사용 패턴

텍스트 생성 및 Whisper ASR

import cc.projectargus.libargus.*;
import java.lang.foreign.Arena;
import java.nio.file.Path;

public class Main {
    public static void main(String[] args) {
        ArgusBackend.init();
        try (Arena arena = Arena.ofConfined();
             ArgusModel model = ArgusModel.load(arena, Path.of("models/llama-3-8b.gguf"), 99, true)) {

            ArgusContextConfig cfg = new ArgusContextConfig.Builder(4096)
                .cpuThreads(8)
                .typeK(ArgusContextConfig.KV_TYPE_Q4_0)
                .typeV(ArgusContextConfig.KV_TYPE_Q4_0)
                .build();

            try (ArgusContext ctx = ArgusContext.init(arena, model, cfg)) {
                // Insert tokenization, evaluation, and sampling calls here
            }
        } finally {
            ArgusBackend.free();
        }
    }
}

API는 Arena.ofConfined()를 사용하여 오프‑힙 메모리를 할당하며, try‑with‑resources 블록이 종료될 때 자동으로 해제됩니다.

멀티모달 프롬프트 (시각, 오디오, 비디오)

try (Arena arena = Arena.ofConfined();
     ArgusModel base = ArgusModel.load(arena, Path.of("models/qwen2-vl-7b-it.gguf"), 99, true);
     ArgusContext ctx = ArgusContext.init(arena, base,
         new ArgusContextConfig.Builder(8192).build());
     ArgusMultimodalContext mctx = ArgusMultimodalContext.init(
         arena, base, Path.of("models/qwen2-vl-7b-it.mmproj"), 4, true)) {

    try (ArgusBitmap img = ArgusBitmap.loadFile(arena, mctx, Path.of("media/cat.png"), false)) {
        String prompt = "< __media__ >\nDescribe what you see in this image.";
        try (ArgusInputChunks chunks = mctx.tokenize(arena, prompt, true, List.of(img))) {
            int newPos = ctx.evalMultimodalChunks(mctx, chunks, 0, 0, 1024, true);
            System.out.println("Prompt evaluated, new position: " + newPos);
        }
    }
}

멀티모달 프로젝터는 원시 비트맵을 GPU에 자동으로 투사하고, M‑RoPE 위치 그리드를 구축하며, 결과 토큰 스트림을 텍스트 컨텍스트와 통합합니다.

프레임‑단위 비디오 처리

try (ArgusVideo video = ArgusVideo.loadFile(arena, mctx,
        Path.of("media/video.mp4"), 4.0f, 5000);
     ArgusVideoItem item = new ArgusVideoItem()) {
    while (video.readNext(item)) {
        if (item.bitmap() != null) {
            // Process raw RGB frame (no Java copy)
        } else if (item.text() != null) {
            System.out.println("Timestamp chunk: " + item.text());
        }
    }
}

비디오 프레임은 비관리 ArgusBitmap 객체로 제공되어 중간 바이트‑배열 할당을 피합니다.

제로 할당 로짓 바이어스 조정

try (Arena arena = Arena.ofConfined()) {
    int[] tokens = {151644, 151645}; // Example "think" tags
    float[] values = {-Float.MAX_VALUE, -Float.MAX_VALUE};
    MemorySegment bias = arena.allocate(ArgusLayouts.LOGIT_BIAS, tokens.length);
    for (int i = 0; i < tokens.length; i++) {
        bias.setAtIndex(ValueLayout.JAVA_INT, i * 2, tokens[i]);
        bias.setAtIndex(ValueLayout.JAVA_FLOAT, i * 2 + 1, values[i]);
    }
    while (generating) {
        ctx.decodeBatch(batch);
        int token = ctx.sampleTokenWithBias(seqId, temperature, repeatPenalty, bias, tokens.length);
        if (token == model.vocabEos()) break;
    }
}

바이어스 세그먼트는 생성 루프 외부에서 한 번 할당되어 제로 할당 샘플링을 보장합니다.

검증 및 테스트

  • 네이티브 C 단위 테스트는 ./build/test_libargus를 통해 실행됩니다.
  • Java 통합 테스트는 bindings/java 디렉터리에서 Gradle(gradle test)로 실행됩니다.
  • 테스트 스위트는 텐서 경계 준수, 스레드 재진입성, 및 올바른 메타데이터 내성을 검증합니다.

엔지니어링 방법론

인간 주도 설계는 모든 메모리 레이아웃, 오프‑힙 수명 주기, 하드웨어‑특정 최적화를 정의합니다. AI 지원 코드 생성은 JNI‑스타일 바인딩 스텁과 같은 반복적인 보일러플레이트에만 제한되어, 성능‑중요 경로가 직접적인 인간 제어 하에 유지됩니다.

커뮤니티 반응 (Hacker News 댓글)

@hi_hi: "이것의 장점이 무엇인가요? 뭔가 속도가 개선되는 것 같은데…? AI를 사용할 때 대부분은 LLM에서 오기 때문에, 이것이 무엇을 개선하는지 궁금합니다."

주요 장점은 JVM 힙 복사와 VRAM 단편화를 제거하는 것입니다. 텐서를 네이티브 메모리에 보관하고 단일 백엔드 인스턴스를 공유함으로써, libargus는 파이프라인의 모든 단계—LLM 전방 패스뿐만 아니라—에 대한 지연 시간을 감소시킵니다.

@RandomBK: "전통적인 경로에서 어떤 병목 현상을 겪었는지 궁금합니다… 원시 입력/출력을 섞는 것이 전체 비용의 사소한 부분일 것이라고 생각했는데요."

전통적인 Java 바인딩은 토큰, 오디오 샘플, 비디오 프레임에 대해 int[]/float[]를 할당하여 GC 압력과 추가 memcpy 작업을 유발합니다. 고처리량 시나리오(예: 스트리밍 비디오 캡션)에서는 이러한 복사가 전체 추론 시간의 가시적인 비율을 차지합니다. libargus는 그 오버헤드를 완전히 제거합니다.

@exabrial: "꽤 인상적이네요."

이 댓글은 제로 할당 멀티모달 런타임이 Java 기반 AI 작업에 있어 중요한 진전이라는 커뮤니티의 인식을 강조합니다.

로드맵 및 라이선스

  • libargus는 Layer 0으로 위치하며, 향후 상위 수준 인지 서비스(Layer 1 상태ful 코어, 대시보드 등)를 위한 핵심 실행 기반을 제공합니다.
  • 이 프로젝트는 MIT 라이선스를 따르며, 상위 llama.cpp, libmtmd, whisper.cpp 코드를 호환 가능한 조건으로 포함합니다.

기사 끝

Sources

관련

  • Dispatch
  • Dispatch
  • 프로젝트
  • Dispatch