Skip to content

Commit dac2841

Browse files
astrelskyGemini AICopilotandrej
authored
Windows support (#136)
* Windows support - Switched to using ``time.perf_counter_ns`` to prevent divide by 0 errors. - Hoisted object FIFO acquires out of conditional structures to satisfy cyclostatic compiler analysis constraints. - Swapped shell/awk commands for platform-independent Python execution blocks to handle symbol mapping on Windows. - Added test skip validation for missing gated weights to stabilize local test executions. Co-authored-by: Gemini AI <gemini-ai@google.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix formatting issue and revert mha changes --------- Co-authored-by: Gemini AI <gemini-ai@google.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: André Rösti <an.roesti@gmail.com>
1 parent 2bc7f53 commit dac2841

2 files changed

Lines changed: 40 additions & 15 deletions

File tree

iron/applications/llama_3.2_1b/test.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import subprocess
66
import pytest
77
import os
8+
import sys
89
from pathlib import Path
910

1011
test_dir = Path(__file__).parent
@@ -27,14 +28,21 @@ def generate_test_params():
2728
params, names = generate_test_params()
2829

2930

31+
@pytest.mark.skipif(
32+
not (
33+
(weights_dir / "llama3.2-1b" / "model.safetensors").exists()
34+
and (weights_dir / "llama3.2-1b" / "tokenizer.model").exists()
35+
),
36+
reason="llama3.2-1b weights not found",
37+
)
3038
@pytest.mark.supported_devices("npu2")
3139
@pytest.mark.metrics(
3240
TTFT=r"\[Prefill\]\s*Time to first token:\s*(?P<value>[\d\.e\+-]+) s",
3341
TPS=r"\[Decode\]\s*Tokens per second:\s*(?P<value>[\d\.e\+-]+)",
3442
)
3543
@pytest.mark.parametrize("prompt_len,num_tokens", params, ids=names)
3644
def test_llama_3_2_1b(prompt_len, num_tokens):
37-
command = f"python3 {test_dir}/llama_npu.py {weights_dir}/llama3.2-1b/model.safetensors {weights_dir}/llama3.2-1b/tokenizer.model --num-tokens {num_tokens} --prompt-len {prompt_len}"
45+
command = f"{sys.executable} {test_dir}/llama_npu.py {weights_dir}/llama3.2-1b/model.safetensors {weights_dir}/llama3.2-1b/tokenizer.model --num-tokens {num_tokens} --prompt-len {prompt_len}"
3846

3947
result = subprocess.run(
4048
command,

iron/common/compilation/base.py

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -795,20 +795,37 @@ def _prefix_symbols(self, artifact, prefix):
795795
nm_path = self._find_working_tool("llvm-nm")
796796
symbol_map_file = artifact.filename + ".symbol_map"
797797

798-
# Extract defined symbols and build the redefine-syms map. Run nm to a
799-
# file, THEN awk (joined by `&&`) rather than `nm | awk`: a pipe reports
800-
# only awk's exit status, so a failing nm silently produces an EMPTY map
801-
# and the prefix rename is skipped, surfacing much later as
802-
# `undefined symbol: {prefix}<sym>` at the per-core link. With `&&` a
803-
# failed nm aborts here loudly instead.
804-
nm_cmd = [
805-
"sh",
806-
"-c",
807-
f"{nm_path} --defined-only --extern-only {artifact.filename} "
808-
f"> {symbol_map_file}.syms && "
809-
f"awk '{{print $3 \" {prefix}\" $3}}' {symbol_map_file}.syms "
810-
f"> {symbol_map_file}",
811-
]
798+
if os.name == "nt":
799+
# Pure python code execution block wrapped cleanly for Windows
800+
python_script = f"""
801+
import subprocess
802+
nm_cmd = [{repr(nm_path)}, '--defined-only', '--extern-only', {repr(artifact.filename)}]
803+
res = subprocess.run(nm_cmd, capture_output=True, text=True, check=True)
804+
lines = []
805+
for line in res.stdout.splitlines():
806+
parts = line.strip().split()
807+
if len(parts) >= 3:
808+
sym = parts[-1]
809+
lines.append(f"{{sym}} {prefix}{{sym}}\\n")
810+
with open({repr(symbol_map_file)}, 'w') as f:
811+
f.writelines(lines)
812+
"""
813+
nm_cmd = [sys.executable, "-c", python_script.strip()]
814+
else:
815+
# Extract defined symbols and build the redefine-syms map. Run nm to a
816+
# file, THEN awk (joined by `&&`) rather than `nm | awk`: a pipe reports
817+
# only awk's exit status, so a failing nm silently produces an EMPTY map
818+
# and the prefix rename is skipped, surfacing much later as
819+
# `undefined symbol: {prefix}<sym>` at the per-core link. With `&&` a
820+
# failed nm aborts here loudly instead.
821+
nm_cmd = [
822+
"sh",
823+
"-c",
824+
f"{nm_path} --defined-only --extern-only {artifact.filename} "
825+
f"> {symbol_map_file}.syms && "
826+
f"awk '{{print $3 \" {prefix}\" $3}}' {symbol_map_file}.syms "
827+
f"> {symbol_map_file}",
828+
]
812829

813830
# Apply the renaming using the symbol map
814831
objcopy_cmd = [

0 commit comments

Comments
 (0)