Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions .github/actions/compile-models/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: 'Compile Models'
description: 'Compile models for NPU'

inputs:
compiler-type:
description: 'MLIR|DRIVER'
type: string
required: true
npu-platform:
description: 'NPU.XXXX'
type: string
required: true
install-package-dir:
description: 'OV|Driver build artifacts with compile_tool and NPU compiler libs'
type: string
required: true
models-dir:
description: 'Path to a directory with downloaded models'
type: string
required: true
blobs-dir:
description: 'Path to a directory where to save model compilation logs'
type: string
required: true
models-config:
description: 'Path to models config'
type: string
required: true
logs-dir:
description: 'Path to a directory where to save model compilation logs'
type: string
required: true

runs:
using: 'composite'
steps:
- name: Install dependencies
shell: bash
run: |
python3 -m pip install --upgrade pip
python3 -m pip install -r ${{ github.action_path }}/requirements.txt

- name: Prepare OpenVINO environment
if: ${{ inputs.compiler-type == 'MLIR' }}
shell: bash
run: |
cat <<'EOF' > prepare_env.sh
#!/usr/bin/env bash
set -e
INSTALL_PACKAGE_ABS_PATH=$(realpath ${{ inputs.install-package-dir }})
source ${INSTALL_PACKAGE_ABS_PATH}/setupvars.sh
export COMPILE_TOOL=${INSTALL_PACKAGE_ABS_PATH}/tools/compile_tool/compile_tool
EOF
chmod +x ${INSTALL_PACKAGE_ABS_PATH}/setupvars.sh
chmod +x ${INSTALL_PACKAGE_ABS_PATH}/tools/compile_tool/compile_tool
chmod +x prepare_env.sh

- name: Prepare Driver environment
if: ${{ inputs.compiler-type == 'DRIVER' }}
shell: bash
run: |
cat <<'EOF' > prepare_env.sh
#!/usr/bin/env bash
set -e
if [[ "${{ inputs.npu-platform }}" == "NPU.3720" ]]; then
PLATFORM="METEORLAKE"
elif [[ "${{ inputs.npu-platform }}" == "NPU.4000" ]]; then
PLATFORM="LUNARLAKE"
else
PLATFORM="not_valid_platform"
fi
INSTALL_PACKAGE_ABS_PATH=$(realpath ${{ inputs.install-package-dir }})
export LD_LIBRARY_PATH=${INSTALL_PACKAGE_ABS_PATH}/usr/lib/:$LD_LIBRARY_PATH
export ZE_INTEL_NPU_PLATFORM_OVERRIDE=${PLATFORM}
export COMPILE_TOOL=${INSTALL_PACKAGE_ABS_PATH}/usr/bin/compile_tool
EOF
chmod +x prepare_env.sh

- name: Compile models for ${{ inputs.npu-platform }} with ${{ inputs.compiler-type }} compiler
shell: bash
run: |
source prepare_env.sh
python3 ${{ github.action_path }}/compile_models.py \
--compiler-type "${{ inputs.compiler-type }}" \
--compile-tool "${COMPILE_TOOL}" \
--models-config "${{ inputs.models-config }}" \
--models-dir "${{ inputs.models-dir }}" \
--blobs-dir "${{ inputs.blobs-dir }}" \
--logs-dir "${{ inputs.logs-dir }}"
68 changes: 68 additions & 0 deletions .github/actions/compile-models/common/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""
Parses command line arguments
"""

import argparse
from pathlib import Path


def parse_arguments():
"""Parses command line arguments"""
parser = argparse.ArgumentParser(
description="Compiling AI models from different sources specified in a json config."
)
parser.add_argument(
"--compiler-type",
type=str,
required=True,
choices=["MLIR", "DRIVER"],
help="MLIR|DRIVER",
)
parser.add_argument(
"--compile-tool",
type=Path,
required=True,
help="Path to the compile_tool executable",
)
parser.add_argument(
"--models-config",
type=Path,
required=True,
help="Path to a JSON configuration file describing models to validate",
)
parser.add_argument(
"--models-dir",
type=Path,
required=True,
help="Path to a directory with models to validate",
)
parser.add_argument(
"--blobs-dir",
type=Path,
required=False,
default=Path("./blobs"),
help="Path to a directory to save compiled models",
)
parser.add_argument(
"--configs-dir",
type=Path,
required=False,
default=Path("./configs"),
help="Path to a directory where to save compilation configs",
)
parser.add_argument(
"--logs-dir",
type=Path,
required=False,
default=Path("./logs"),
help="Path to a directory where to save compilation logs",
)
parser.add_argument(
"--jobs",
type=int,
required=False,
default=4,
help="Number of parallel jobs",
)
args = parser.parse_args()
return args
26 changes: 26 additions & 0 deletions .github/actions/compile-models/common/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
Enums declaration
"""

from enum import Enum


class Status(Enum):
"""Enum class defining possible compilation statuses"""

SUCCESS = 1
SKIPPED = 2
DISABLED = 3
FAILED = 4
TIMEOUT = 5
MODEL_NOT_FOUND = 6

@classmethod
def get_ok_statuses(cls):
"""Returns a set of statuses that don't throw an error"""
return {cls.SUCCESS, cls.SKIPPED, cls.DISABLED}

@classmethod
def get_error_statuses(cls):
"""Returns a set of statuses that causes the script to fail"""
return {cls.FAILED, cls.TIMEOUT, cls.MODEL_NOT_FOUND}
37 changes: 37 additions & 0 deletions .github/actions/compile-models/common/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
Declares and configures loggers
"""

import logging


def setup_thread_file_logger(logs_dir: str, log_file_name: str) -> logging.Logger:
"""Configures and returns a thread-safe file-based logger"""
logger = logging.getLogger(f"logger_{log_file_name}")
logger.setLevel(logging.INFO)
logger.propagate = False
logger.handlers.clear()

log_file_path = logs_dir / f"{log_file_name}.log"
log_file_path.parent.mkdir(parents=True, exist_ok=True)
file_handler = logging.FileHandler(log_file_path, encoding="utf-8")
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
file_handler.setFormatter(formatter)

logger.addHandler(file_handler)
return logger


def setup_console_logger() -> logging.Logger:
"""Configures and returns a console logger"""
logger = logging.getLogger("console_logger")
logger.setLevel(logging.INFO)
logger.propagate = False
logger.handlers.clear()

console_handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
console_handler.setFormatter(formatter)

logger.addHandler(console_handler)
return logger
46 changes: 46 additions & 0 deletions .github/actions/compile-models/common/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
compile-models library helpers
"""

import json
import logging
from collections import Counter
from pathlib import Path

from common.enums import Status


def read_models_from_config(models_config: Path, logger: logging.Logger) -> list:
"""Parses a JSON config and returns a list of model configs as dictionaries"""
with open(models_config, "r", encoding="utf-8") as f:
config = json.load(f)
models = config.get("models", [])
return models


def write_extra_config(args: dict, model: dict) -> tuple:
"""Writes key-value pairs to compile_tool extra config"""
extra_config_path = args.configs_dir / f"{model.get('name')}_config.conf"
extra_config_path.parent.mkdir(parents=True, exist_ok=True)

lines = [f"{key} {value}\n" for key, value in model.get("extra_config", "").items()]
content = "".join(lines)
with open(extra_config_path, "w", encoding="utf-8") as f:
f.write(content)
return extra_config_path, content


def analyze_results(compilation_results: dict, logger: logging.Logger) -> Status:
"""Prints compile_tool statistics across all configured models"""
for model_name, result in compilation_results.items():
if result in Status.get_ok_statuses():
logger.info("%s - %s", result, model_name)
else:
logger.error("%s - %s", result, model_name)
logger.info("Compilation summary:")
counter = Counter(compilation_results.values())
for status in Status:
logger.info("\t%s: %d", status.name, counter.get(status, 0))
if any(counter.get(status, 0) for status in Status.get_error_statuses()):
return Status.FAILED
return Status.SUCCESS
Loading
Loading