Important
Windows ML 런타임 API는 현재 실험적이며 프로덕션 환경에서 사용하는 것이 지원되지 않습니다. 이 API를 시도하는 앱은 Microsoft Store에 게시해서는 안 됩니다.
Windows ML 런타임 API는 Windows용으로 특별히 빌드된 네이티브 로컬 AI 추론 프레임워크입니다. Windows ML 런타임 API를 사용하면 모델 로드, 하드웨어 배치, 텐서 소유권, 파이프라인 컴퍼지션, 컴파일 및 진단을 명시적으로 제어할 수 있습니다.
Windows에서 최상의 모델 추론 성능을 위해 런타임 API를 사용하는 것이 좋지만, 앱이 다른 플랫폼에서 실행되어야 하거나 플랫폼 간 ONNX 런타임 코드가 이미 작동하고 있는 경우 Windows ML을 통해 ONNX 런타임을 사용할 수도 있습니다.
객체가 서로 맞물리는 방식
IWinMLRuntime
|-- loads --> IWinMLModel
|-- creates -> IWinMLExecutionTarget
`-- creates -> IWinMLPipelineBuilder
|-- adds/connects -> IWinMLStage
`-- Build() ------> IWinMLPipeline
IWinMLExecutionTarget -- creates --> IWinMLTensor
IWinMLStage ----------- binds -----> IWinMLTensor
IWinMLPipeline -------- Run() -----> stage outputs
모든 메서드는 HRESULT를 반환하며, 모든 인터페이스 포인터는 일반 COM 참조 카운팅을 따릅니다. 선택적 기능은 QueryInterface로 검색됩니다. 사용할 수 없는 기능은 E_NOINTERFACE를 반환합니다.
Runtime
IWinMLRuntime를 WinMLCreateRuntime 사용하여 만듭니다. 모델 아티팩트 로드, 실행 대상 만들기 및 파이프라인 작성기를 만드는 데 사용합니다.
모델 및 스키마
IWinMLModel 는 변경할 수 없는 내부 구현이 감춰진 모델 아티팩트입니다.
LoadModelFromFile 는 앱에서 읽을 수 있는 절대 또는 상대 파일 경로를 허용합니다. 모델 위치는 앱의 패키징 결정입니다.
로드하면 아티팩트가 인식되고 구조적으로 읽을 수 있음이 확인됨을 의미합니다.
대상 호환성은 파이프라인 작성기의 Build 메서드가 성공하면 나중에 커밋됩니다.
IWinMLModelSchema를 통해 모델의 선언된 서수 스키마를 반영합니다. 일부 ONNX 아티팩트도 선택적 IWinMLOrtModelSchema를 통해 이름을 노출하지만 실행 식별자는 위치 기반으로 유지됩니다.
도형 및 연산자
선언된 모델 스키마에는 UINT64_MAX로 표시되는 자유 차원이 포함될 수 있습니다. 구체적인 IWinMLTensor 는 항상 확정된 차원을 가집니다.
ORT 지원 파이프라인은 자유 차원에 구체적인 값을 바인딩한 상태로 실행할 수 있습니다.
고정 또는 명시적으로 제한된 셰이프는 Build가 호환성을 검증하고, 안정적인 리소스를 할당하며, 재생 또는 디바이스 상주 반복이 적법한지 여부를 판단할 수 있게 해주므로 최적화된 디자인 센터로 유지됩니다. 또한 실행 백 엔드에서 가장 광범위한 호환성을 제공합니다. 이는 선언된 ONNX 스키마에 자유 차원이 포함된 모델의 일괄 거부가 아니라 최적화 및 이식성의 구별입니다.
표준 ONNX 연산자도 마찬가지로 백 엔드 이식성을 향상시킵니다. 모델 로드가 성공한다고 해서 모든 대상이 모든 연산자를 실행할 수 있다고 보장하지는 않습니다. Build에서 호환성 검사를 수행합니다.
Backends
모델 파일은 백 엔드를 선택합니다. 앱은 어느 쪽이든 동일한 런타임 개체, 즉 모델, 실행 대상, 파이프라인 작성기, 스테이지, 바인딩 및 Run를 사용합니다.
| 모델 파일 | Backend | 하드웨어 가속 |
|---|---|---|
.onnx, .ort |
ONNX 런타임 | Windows ML EP 카탈로그를 통해 Windows가 설치하고 최신 상태로 유지하는 실행 공급자(EP) |
.gguf |
llama.cpp | 앱과 함께 배포된 llama.cpp 모듈: 패키지의 CPU 모듈 및 NVIDIA GPU용 선택적 CUDA 모듈입니다. CPU 및 CUDA는 Windows ML이 이 릴리스에서 유효성을 검사하는 유일한 llama.cpp 백엔드입니다. |
백 엔드는 스테이지에서 표현할 수 있는 내용이 다릅니다.
| Capability | ONNX 런타임 | llama.cpp |
|---|---|---|
| 무대 모양 | 모든 ONNX 그래프; 여러 단계를 하나의 파이프라인에서 연결할 수 있습니다. | GGUF 파일당 하나의 디코더 단계: 토큰 ID(입력 0), 로짓 출력(출력 0) |
| 시퀀스 상태(KV 캐시) |
IWinMLStatefulStageOptions로 상태 텐서 쌍을 선언합니다. 런타임에서 이를 관리합니다. |
백엔드에서 관리됨; 선언할 항목 없음 |
| 컨텍스트 길이 |
SetSequenceCapacityHint 이전 Build또는 모델의 선언된 용량 |
SetSequenceCapacityHint before Build는 llama.cpp 컨텍스트 길이를 설정합니다 |
| 공급자 고정 설정 및 ORT 단계 옵션 | 지원됨 (WinMLRuntimeOrt.h) |
지원되지 않습니다. Build 반환합니다 HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED) |
Build 후 배치 보고서 |
IWinMLOrtStageDiagnostics 요청된 공급자와 선택한 공급자를 지정합니다. |
IWinMLStage::GetExecutionTarget CPU 또는 GPU 보고서 |
하나의 파이프라인은 백엔드를 조합할 수 있습니다. 예를 들어 ONNX 런타임의 위스퍼 스테이지는 llama.cpp의 GGUF 언어 모델에 입력을 전달할 수 있습니다.
실행 대상
IWinMLExecutionTarget 는 하드웨어 클래스와, 선택적으로 특정 어댑터를 요청하는 변경할 수 없는 배치 토큰입니다.
Build가 실행될 때 각 백엔드가 이를 해결합니다:
| 스테이징 대상 | ONNX 런타임 | llama.cpp |
|---|---|---|
AddModelStage에 nullptr 전달됨 |
자동 배치는 사용 가능한 경우 호환되는 GPU EP를 선택하고 필요 시 CPU로 대체합니다. | CUDA 모듈이 배포된 경우 모델이 적합하면 해당 모듈로 오프로드합니다. 그렇지 않으면 CPU에서 실행됩니다. |
CreateCpuExecutionTarget |
ORT의 CPU 공급자를 기준으로 사용하여 호환되는 CPU EP를 선택합니다. | CPU에서 실행됩니다. |
CreateExecutionTarget GPU 종류와 함께 CreateExecutionTargetFromAdapter 또는 CreateExecutionTargetFromD3D12 |
어댑터 ID를 호환되는 GPU EP 디바이스에 매핑합니다. 일치하는 공급자 디바이스가 없으면 Build 실패합니다. |
CUDA 모듈에 대한 부분 오프로드가 필요합니다.
Build는 CUDA 모듈이 배포되지 않은 경우 HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY)를 반환하고, 모델이 맞지 않는 경우 HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)를 반환합니다. 모듈은 GPU를 선택합니다. 어댑터 ID가 사용되지 않습니다. |
CreateExecutionTarget NPU 유형 또는 NPU 어댑터 |
호환되는 NPU EP 디바이스에 매핑합니다. | 지원되지 않습니다. Build는 HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)를 반환합니다. |
IWinMLOrtCompatibility::CreateExecutionTarget(provider, kind, hardwareTarget) |
등록된 EP 1개 고정
hardwareTarget를 nullptr(으)로 설정하면 런타임은 공급자를 자체 디바이스 중 하나와 페어링합니다. GPU가 두 개 있는 PC에서는 이렇게 하면 공급자가 지원하지 않는 어댑터와 페어링되는 것을 방지합니다. |
지원되지 않으며, Build는 HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)를 반환합니다. |
IWinMLRuntime::CreateExecutionTarget(kind, preference) 는 디바이스를 직접 열거할 필요 없이 요청된 클래스의 어댑터를 선택하고, preference 는 통합 GPU 및 외장 GPU와 같이 둘 이상이 있는 경우 어댑터의 우선순위를 매깁니다.
ComPtr<IWinMLExecutionTarget> target;
THROW_IF_FAILED(runtime->CreateExecutionTarget(
WINML_EXECUTION_TARGET_KIND_GPU,
WINML_EXECUTION_TARGET_PREFERENCE_PERFORMANCE,
target.GetAddressOf()));
명시적 어댑터를 선택하려면 호환되는 ONNX 런타임 공급자가 ORT를 통해 해당 하드웨어 ID를 노출해야 합니다. 일치하는 Build에 해당하는 공급자 디바이스가 없으면 다른 어댑터 또는 CPU를 자동으로 선택하지 않고 실패합니다.
CreateExecutionTargetFromD3D12 는 대상에서 호출자의 디바이스 및 선택적 큐를 유지하지만 ORT 실행은 EP 선택에 어댑터 ID만 사용합니다. ORT 공급자는 실행 리소스를 소유하며 호출자의 명령 큐는 ORT 제출에 사용되지 않습니다.
D3D12 대상은 여전히 QueryInterface부터 IWinMLD3D12ExecutionTarget까지 노출됩니다. 단계 간에 하나의 명시적 대상을 다시 사용하는 것은 동일한 어댑터 선호도를 나타냅니다. 서로 다른 대상은 전송 경계를 명시적으로 만듭니다.
GGUF 모델 실행하기
-
LoadModelFromFile로 파일을 로드합니다. 확장 프로그램에서.ggufllama.cpp를 선택합니다. 분할된 모델의 경우 모든 샤드를 한 폴더에 유지하고 첫 번째 샤드를 로드합니다. - CPU, GPU 또는
nullptr대상이 있는 모델 단계를 하나 추가합니다. 컨텍스트 길이를 설정하려면 스테이지에서IWinMLStatefulStageOptions를 쿼리하고SetSequenceCapacityHint를 호출합니다. -
Build을 호출합니다. 그런 다음 프롬프트의 토큰 ID를 입력 0에 바인딩하고 출력 0을 요청한 다음Run를 호출합니다. 나중에 실행할 때마다 다음 토큰을 사용합니다. 백 엔드는 실행 간에 KV 캐시를 유지합니다. - 독립 시퀀스 전에
ResetExecutionState를 호출합니다.
// Create the runtime and an execution target (CPU here; GPU also available).
ComPtr<IWinMLRuntime> runtime;
THROW_IF_FAILED(WinMLCreateRuntime(IID_PPV_ARGS(runtime.GetAddressOf())));
ComPtr<IWinMLExecutionTarget> target;
THROW_IF_FAILED(runtime->CreateCpuExecutionTarget(target.GetAddressOf()));
ComPtr<IWinMLModel> model;
THROW_IF_FAILED(runtime->LoadModelFromFile(
L"C:\\models\\qwen2.5-0.5b-instruct.gguf", nullptr, model.GetAddressOf()));
ComPtr<IWinMLPipelineBuilder> builder;
THROW_IF_FAILED(runtime->CreatePipelineBuilder(builder.GetAddressOf()));
ComPtr<IWinMLStage> stage;
THROW_IF_FAILED(builder->AddModelStage(
model.Get(), target.Get(), L"decoder", stage.GetAddressOf()));
THROW_IF_FAILED(stage->RequestOutput(0));
// Set the llama.cpp context length before Build.
ComPtr<IWinMLStatefulStageOptions> stateOptions;
THROW_IF_FAILED(stage->QueryInterface(IID_PPV_ARGS(stateOptions.GetAddressOf())));
THROW_IF_FAILED(stateOptions->SetSequenceCapacityHint(4096));
ComPtr<IWinMLPipeline> pipeline;
THROW_IF_FAILED(builder->Build(pipeline.GetAddressOf()));
// Bind token IDs to input 0 and run one token at a time; the backend keeps
// the KV cache between runs.
THROW_IF_FAILED(stage->BindInput(0, tokenIdsTensor.Get()));
THROW_IF_FAILED(pipeline->Run());
ComPtr<IWinMLTensor> logits;
THROW_IF_FAILED(stage->GetOutput(0, logits.GetAddressOf()));
// Start an independent sequence on the same pipeline.
THROW_IF_FAILED(pipeline->ResetExecutionState());
토케나이저 및 대화 서식은 GGUF 파일에서 가져오므로 GGUF 모델에는 별도의 토케나이저 파일이 필요하지 않습니다. 토큰 루프를 건너뛰려면 GGUF 및 ONNX 모델과 함께 작동하는 텍스트 생성 API를 사용하세요.
llama.cpp 백엔드를 배포
llama.cpp 백엔드는 앱 로컬 방식입니다. 프로젝트가 옵트인되면 Windows ML NuGet 패키지는 런타임의 llama.cpp 어댑터, llama.cpp 코어 및 CPU 모듈을 앱 옆에 복사합니다. GPU 가속에는 패키지와 동일한 llama.cpp 리비전용으로 빌드되고 앱 옆에 배치되는 선택적 CUDA 모듈이 필요합니다.
두 단계에 대한 자세한 안내는 GGUF 모델 샘플 및 llama.cpp 샘플을 참조하세요.
파이프라인 및 단계
원샷 IWinMLPipelineBuilder으로 파이프라인을 빌드합니다.
- 실행 대상이 있는 모델 또는 프로세서 단계를 추가합니다.
- 순서 인덱스를 기준으로 스테이지 포트를 연결합니다.
-
Build를 한 번 호출하여 그래프를 고정하고, 배치를 해결하고, 호환성을 검증합니다.
두 모델 단계의 경우 두 단계를 추가하고 첫 번째 단계의 출력 인덱스를 두 번째 단계의 입력 인덱스에 연결하고 한 번 빌드합니다. 앱은 모델을 제공하고 외부 입력을 바인딩합니다. 모델별 런타임 API는 필요하지 않습니다. 임베딩, 디코더, 이미지 전처리 및 기타 애플리케이션 아키텍처는 동일한 스테이지 및 텐서 프리미티브를 사용합니다.
각 IWinMLStage은 위치 입력 바인딩을 소유하며 현재 출력 텐서를 노출합니다. 입력 바인딩은 실행 간에 유지됩니다. 앱이 출력 스토리지를 제공할 때 실행 전에 BindOutput를 호출합니다.
선택적 단계 기능에는 해결된 대상, 구체화된 스키마, 출력 상주 정책 및 시퀀스 상태 제어가 포함됩니다. 각 기능을 테스트하려면 QueryInterface를 사용하세요.
파이프라인 실행
IWinMLPipeline::Run 는 준비된 파이프라인을 동기적으로 실행합니다. 독립 시퀀스 사이에서 ResetExecutionState를 호출하여 런타임 관리 상태를 지웁니다.
선택적 실행 인터페이스는 빌드된 그래프와 선택한 백 엔드가 지원될 때 디바이스 타임라인 제출 및 고정 개수 반복 재생을 제공합니다. 기본 Run 경로는 공통 기준선으로 유지됩니다.
텐서 및 락
IWinMLTensor는 유형이 지정된 다차원 데이터를 나타냅니다. 실행 대상에서 쿼리된 팩터리에서 텐서를 만들어 텐서 배치가 대상 배치를 따르도록 합니다.
팩터리에는 원시 바이트, 이미지 데이터, 오디오 데이터, 토큰 ID 및 구성 가능한 텐서 프로세서가 포함됩니다. 선택적 텐서 인터페이스는 변경, D3D12 버퍼 바인딩 및 동기화를 노출합니다.
CPU에서 텐서 바이트에 액세스하기 전에 IWinMLTensor::Lock를 호출하세요. 반환된 IWinMLTensorDataLock은 CPU 액세스 창을 설정하고 필요한 매핑 또는 동기화를 수행하며 GetData에서 반환된 포인터의 수명을 관리합니다.
컴파일 및 외부 가중치
사전 컴파일은 실행 대상을 통해 IWinMLModelCompiler노출되는 선택적 기능입니다. 컴파일된 아티팩트가 일반적인 모델 로딩 방법을 통해 다시 로드됩니다. 앱은 IWinMLResourceMapReader를 통해 외부화된 가중치를 제공할 수 있습니다.
텍스트 작업 부하
텍스트 워크로드는 동일한 런타임, 대상, 파이프라인, 스테이지 및 텐서 프리미티브를 사용합니다. 앱은 모델 패키지 메타데이터, 샘플링, 중지 정책 및 생성된 토큰 누적을 직접 관리하거나 텍스트 생성 API를 사용하여 호환되는 런타임 파이프라인을 통해 해당 작업을 조정할 수 있습니다.
IWinMLTokenizer 는 하위 수준 인코딩 및 디코딩 작업을 제공합니다. 한 IWinMLTokenizerDecoder는 하나의 시퀀스에 대해 독립적인 증분 디코딩 커서를 유지 관리합니다. 텍스트 생성 API는 기본 런타임 개체의 소유권을 변경하지 않고 텍스트 생성 세션, 옵션, 스트리밍 업데이트, 취소, 완료 이유 및 완료된 결과를 추가합니다.
ONNX 런타임 호환성
WinMLRuntimeOrt.h의 선택적 인터페이스는 ONNX에 다음과 같은 편의를 제공합니다:
-
IWinMLOrtCompatibility는 이미 등록된 ONNX 런타임 실행 공급자를 선택합니다. -
IWinMLOrtModelSchema은 입력 및 출력 이름을 반영합니다. -
IWinMLOrtNamedBindings는 ORT 지원 스테이지를 이름으로 바인딩합니다. -
IWinMLOrtStageDiagnosticsBuild이후 요청된 보고서 및 선택된 공급자.
이러한 인터페이스는 설치 중에 이름 및 공급자 정책을 확인 및 결정합니다. 실행은 동일한 인자 위치 기반 파이프라인 계약을 계속 사용합니다.
자동으로 IWinMLOrtCompatibility가 하나를 선택하도록 두는 대신, 런타임에서 Build를 쿼리하여 ONNX 모델 단계를 이미 등록한 실행 공급자에 고정합니다.
ComPtr<IWinMLOrtCompatibility> ortCompatibility;
THROW_IF_FAILED(runtime->QueryInterface(IID_PPV_ARGS(ortCompatibility.GetAddressOf())));
ComPtr<IWinMLExecutionTarget> target;
THROW_IF_FAILED(ortCompatibility->CreateExecutionTarget(
L"MyRegisteredProvider",
WINML_EXECUTION_TARGET_KIND_GPU,
/* hardwareTarget */ nullptr,
target.GetAddressOf()));
nullptr에 hardwareTarget를 전달하면 런타임은 해당 하드웨어 클래스의 자체 디바이스 중 하나와 공급자를 페어링하고, 대신 공급자를 해당 특정 어댑터에 고정하려면 기존 IWinMLExecutionTarget를 전달하십시오.
.gguf 스테이지에서는 이 대상을 지원하지 않습니다. HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)은(는) Build를 반환합니다.