Skip to content

Commit 077867b

Browse files
committed
refactor(build): select InfiniOps implementations from JSON
1 parent febfe97 commit 077867b

7 files changed

Lines changed: 123 additions & 79 deletions

File tree

‎csrc/infinicore/src/ops/random_sample/random_sample_infiniops.cc‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ void calculate(
5757
infini::ops::Handle handle;
5858
handle.set_stream(context::getStream());
5959
infini::ops::Config config;
60+
infini::ops::Config sampling_config;
61+
static const auto implementation_index = []() {
62+
const auto indices = infini::ops::TopKTopPSamplingFromLogits::active_implementation_indices(
63+
infini::ops::Device::Type::kNvidia);
64+
INFINICORE_ASSERT(!indices.empty());
65+
return indices.front();
66+
}();
67+
sampling_config.set_implementation_index(implementation_index);
6068

6169
auto logits_2d = logits->view({1, logits->numel()});
6270
Tensor sampled_logits = logits_2d;
@@ -112,7 +120,7 @@ void calculate(
112120
const std::optional<int64_t> offset{0};
113121
infini::ops::TopKTopPSamplingFromLogits::Call(
114122
handle,
115-
config,
123+
sampling_config,
116124
TensorMeta(sampled_logits).tensor(sampled_logits),
117125
top_k_tensor,
118126
top_p_tensor,

‎docs/superpowers/specs/2026-07-16-infini-stack-repository-boundaries-design.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ InfiniLM will own these files:
8282

8383
```text
8484
scripts/build_infini_stack.py
85-
scripts/configs/infiniops_ops.txt
85+
scripts/configs/infiniops_ops.json
8686
test/scripts/test_build_infini_stack.py
8787
```
8888

‎scripts/build_infini_stack.py‎

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,41 @@
99
from typing import Dict, List, Mapping, Optional, Sequence
1010

1111
PROJECT_ROOT = Path(__file__).resolve().parents[1]
12-
OPERATOR_SET = PROJECT_ROOT / "scripts/configs/infiniops_ops.txt"
13-
LINKED_OPERATORS = (
14-
"flash_attn_varlen_func",
15-
"flash_attn_with_kvcache",
16-
)
12+
OPERATOR_CONFIG = PROJECT_ROOT / "scripts/configs/infiniops_ops.json"
1713
SUBMODULES = {
1814
"InfiniRT": Path("submodules/InfiniRT"),
1915
"InfiniOps": Path("submodules/InfiniOps"),
2016
"InfiniCCL": Path("submodules/InfiniCCL"),
2117
}
2218

2319

24-
def read_operator_set(path: Path = OPERATOR_SET) -> List[str]:
25-
operators = [line.strip() for line in path.read_text(encoding="utf-8").splitlines()]
26-
operators = [operator for operator in operators if operator]
27-
if not operators:
28-
raise ValueError(f"Operator set is empty: {path}")
29-
if len(operators) != len(set(operators)):
30-
raise ValueError(f"Operator set contains duplicates: {path}")
31-
if operators != sorted(operators):
32-
raise ValueError(f"Operator set must be sorted: {path}")
33-
return operators
20+
def read_operator_config(path: Path = OPERATOR_CONFIG) -> Dict[str, Dict[str, object]]:
21+
config = json.loads(path.read_text(encoding="utf-8"))
22+
if not isinstance(config, dict) or not config:
23+
raise ValueError(f"Operator config must be a non-empty object: {path}")
24+
if list(config) != sorted(config):
25+
raise ValueError(f"Operator config must be sorted: {path}")
26+
for operator, selection in config.items():
27+
if not isinstance(operator, str) or not operator:
28+
raise ValueError(f"Operator names must be non-empty strings: {path}")
29+
if not isinstance(selection, dict) or set(selection) != {"implementations"}:
30+
raise ValueError(
31+
f"Operator {operator!r} must define only 'implementations': {path}"
32+
)
33+
implementations = selection["implementations"]
34+
if (
35+
not isinstance(implementations, list)
36+
or not implementations
37+
or any(
38+
type(slot) is not int or not 0 <= slot < 32 for slot in implementations
39+
)
40+
or len(implementations) != len(set(implementations))
41+
):
42+
raise ValueError(
43+
f"Operator {operator!r} implementations must be unique "
44+
f"integers between 0 and 31: {path}"
45+
)
46+
return config
3447

3548

3649
def parse_gitlink(output: str, relative_path: Path) -> str:
@@ -152,7 +165,7 @@ def build_infiniops_commands(
152165
build_type: str,
153166
jobs: int,
154167
cuda_arch: Optional[str],
155-
operators: Sequence[str],
168+
operator_config: Path,
156169
) -> List[List[str]]:
157170
configure = [
158171
"cmake",
@@ -163,14 +176,12 @@ def build_infiniops_commands(
163176
"-DWITH_CPU=ON",
164177
"-DWITH_NVIDIA=ON",
165178
"-DWITH_LINKED=ON",
166-
f"-DINFINI_OPS_LINKED_OPS={','.join(LINKED_OPERATORS)}",
167179
"-DWITH_TORCH=ON",
168-
"-DINFINI_OPS_TORCH_OPS=argmax",
169180
"-DAUTO_DETECT_DEVICES=OFF",
170181
"-DAUTO_DETECT_BACKENDS=OFF",
171182
"-DGENERATE_PYTHON_BINDINGS=OFF",
172183
f"-DINFINI_RT_ROOT={prefix}",
173-
f"-DINFINI_OPS_OPS={','.join(operators)}",
184+
f"-DINFINI_OPS_OPS={operator_config}",
174185
f"-DCMAKE_BUILD_TYPE={build_type}",
175186
f"-DCMAKE_INSTALL_PREFIX={prefix}",
176187
]
@@ -263,7 +274,7 @@ def write_manifest(
263274
infinilm_revision: str,
264275
infinicore_revision: str,
265276
revisions: Mapping[str, str],
266-
operators: Sequence[str],
277+
operator_config: Mapping[str, Mapping[str, object]],
267278
prefix: Path,
268279
build_type: str,
269280
cuda_arch: Optional[str],
@@ -278,7 +289,11 @@ def write_manifest(
278289
"infinilm": infinilm_revision,
279290
"install_prefix": str(prefix),
280291
"jobs": jobs,
281-
"operators": list(operators),
292+
"operators": list(operator_config),
293+
"operator_implementations": {
294+
operator: selection["implementations"]
295+
for operator, selection in operator_config.items()
296+
},
282297
"submodules": dict(revisions),
283298
"test": test,
284299
}
@@ -362,7 +377,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
362377
build_root = resolve_from_project(args.build_root)
363378
prefix = build_root / "prefix"
364379
manifest_path = build_root / "manifest.json"
365-
operators = read_operator_set()
380+
operator_config = read_operator_config()
366381
revisions = {
367382
name: validate_submodule(infinicore_root, relative_path)
368383
for name, relative_path in SUBMODULES.items()
@@ -376,7 +391,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
376391
print(f"InfiniRT: {revisions['InfiniRT']}")
377392
print(f"InfiniOps: {revisions['InfiniOps']}")
378393
print(f"InfiniCCL: {revisions['InfiniCCL']}")
379-
print(f"Operators ({len(operators)}): {','.join(operators)}")
394+
print(f"Operators ({len(operator_config)}): {','.join(operator_config)}")
380395

381396
if not args.dry_run:
382397
manifest_path.unlink(missing_ok=True)
@@ -402,7 +417,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
402417
args.build_type,
403418
args.jobs,
404419
args.cuda_arch,
405-
operators,
420+
OPERATOR_CONFIG,
406421
):
407422
run(command, PROJECT_ROOT, integration_env, args.dry_run)
408423

@@ -423,7 +438,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
423438
infinilm_revision,
424439
infinicore_revision,
425440
revisions,
426-
operators,
441+
operator_config,
427442
prefix,
428443
args.build_type,
429444
args.cuda_arch,

‎scripts/configs/infiniops_ops.json‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"add": {"implementations": [0]},
3+
"argmax": {"implementations": [8]},
4+
"causal_softmax": {"implementations": [0]},
5+
"convolution": {"implementations": [0]},
6+
"copy": {"implementations": [0]},
7+
"embedding": {"implementations": [0]},
8+
"fill": {"implementations": [0]},
9+
"flash_attn_varlen_func": {"implementations": [16]},
10+
"flash_attn_with_kvcache": {"implementations": [16]},
11+
"fused_add_rms_norm": {"implementations": [0]},
12+
"gelu": {"implementations": [0]},
13+
"gemm": {"implementations": [0]},
14+
"mul": {"implementations": [0]},
15+
"relu": {"implementations": [0]},
16+
"reshape_and_cache_flash": {"implementations": [0]},
17+
"rms_norm": {"implementations": [0]},
18+
"rotary_embedding": {"implementations": [0]},
19+
"sigmoid": {"implementations": [0]},
20+
"silu": {"implementations": [0]},
21+
"silu_and_mul": {"implementations": [0]},
22+
"softmax": {"implementations": [0]},
23+
"top_k_top_p_sampling_from_logits": {"implementations": [16]},
24+
"topk_softmax": {"implementations": [0]}
25+
}

‎scripts/configs/infiniops_ops.txt‎

Lines changed: 0 additions & 23 deletions
This file was deleted.

‎test/scripts/test_build_infini_stack.py‎

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ def _patch_main_dependencies(self, stack, args):
5353
)
5454
return run, write_manifest
5555

56-
def test_operator_set_is_stable(self):
57-
operators = build_infini_stack.read_operator_set()
56+
def test_operator_config_is_stable(self):
57+
config = build_infini_stack.read_operator_config()
5858

5959
self.assertEqual(
60-
operators,
60+
list(config),
6161
[
6262
"add",
6363
"argmax",
@@ -84,15 +84,23 @@ def test_operator_set_is_stable(self):
8484
"topk_softmax",
8585
],
8686
)
87-
self.assertTrue(all("_infinilm" not in operator for operator in operators))
88-
89-
def test_invalid_operator_set_is_rejected(self):
87+
self.assertEqual(
88+
config["top_k_top_p_sampling_from_logits"]["implementations"], [16]
89+
)
90+
self.assertEqual(config["argmax"]["implementations"], [8])
91+
self.assertEqual(config["flash_attn_varlen_func"]["implementations"], [16])
92+
self.assertEqual(config["flash_attn_with_kvcache"]["implementations"], [16])
93+
self.assertEqual(config["topk_softmax"]["implementations"], [0])
94+
self.assertEqual(config["add"]["implementations"], [0])
95+
self.assertTrue(all("_infinilm" not in operator for operator in config))
96+
97+
def test_invalid_operator_config_is_rejected(self):
9098
with tempfile.TemporaryDirectory() as directory:
91-
path = Path(directory) / "ops.txt"
92-
path.write_text("rms_norm\nadd\nadd\n", encoding="utf-8")
99+
path = Path(directory) / "ops.json"
100+
path.write_text('{"add": {"implementations": [32]}}', encoding="utf-8")
93101

94-
with self.assertRaisesRegex(ValueError, "duplicates"):
95-
build_infini_stack.read_operator_set(path)
102+
with self.assertRaisesRegex(ValueError, "between 0 and 31"):
103+
build_infini_stack.read_operator_config(path)
96104

97105
def test_parse_gitlink(self):
98106
output = "160000 commit abcdef1234567890\tsubmodules/InfiniRT\n"
@@ -266,28 +274,20 @@ def test_infiniops_commands_use_pinned_runtime_and_operator_set(self):
266274
"Release",
267275
8,
268276
"sm_80",
269-
[
270-
"add",
271-
"flash_attn_varlen_func",
272-
"flash_attn_with_kvcache",
273-
"rms_norm",
274-
],
277+
Path("ops.json"),
275278
)
276279

277280
configure = commands[0]
278281
self.assertIn(f"-DINFINI_RT_ROOT={Path('build/prefix')}", configure)
279-
self.assertIn(
280-
"-DINFINI_OPS_OPS="
281-
"add,flash_attn_varlen_func,flash_attn_with_kvcache,rms_norm",
282-
configure,
283-
)
282+
self.assertIn(f"-DINFINI_OPS_OPS={Path('ops.json')}", configure)
284283
self.assertIn("-DWITH_LINKED=ON", configure)
285-
self.assertIn(
286-
"-DINFINI_OPS_LINKED_OPS=flash_attn_varlen_func,flash_attn_with_kvcache",
287-
configure,
288-
)
289284
self.assertIn("-DWITH_TORCH=ON", configure)
290-
self.assertIn("-DINFINI_OPS_TORCH_OPS=argmax", configure)
285+
self.assertFalse(
286+
any(option.startswith("-DINFINI_OPS_LINKED_OPS=") for option in configure)
287+
)
288+
self.assertFalse(
289+
any(option.startswith("-DINFINI_OPS_TORCH_OPS=") for option in configure)
290+
)
291291
self.assertIn("-DCMAKE_CUDA_ARCHITECTURES=80", configure)
292292
self.assertEqual(commands[1][3:5], ["--target", "infiniops"])
293293
self.assertEqual(commands[-1], ["cmake", "--install", str(Path("build/ops"))])
@@ -478,7 +478,10 @@ def test_manifest_records_revisions_operators_and_options(self):
478478
"InfiniOps": "ops-sha",
479479
"InfiniCCL": "ccl-sha",
480480
},
481-
["add", "rms_norm"],
481+
{
482+
"add": {"implementations": [0]},
483+
"rms_norm": {"implementations": [0]},
484+
},
482485
Path("prefix"),
483486
"Release",
484487
"sm_80,sm_90a",
@@ -493,6 +496,10 @@ def test_manifest_records_revisions_operators_and_options(self):
493496
self.assertEqual(manifest["submodules"]["InfiniRT"], "rt-sha")
494497
self.assertEqual(manifest["submodules"]["InfiniCCL"], "ccl-sha")
495498
self.assertEqual(manifest["operators"], ["add", "rms_norm"])
499+
self.assertEqual(
500+
manifest["operator_implementations"],
501+
{"add": [0], "rms_norm": [0]},
502+
)
496503
self.assertEqual(manifest["install_prefix"], str(Path("prefix")))
497504
self.assertEqual(manifest["build_type"], "Release")
498505
self.assertEqual(manifest["cuda_arch"], "sm_80,sm_90a")

‎test/static/test_infinicore_runtime_contracts.py‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ def test_infiniops_adapters_do_not_use_infinilm_suffixed_apis(self) -> None:
107107
source, re.compile(r"infini::ops::[A-Za-z0-9_]*Infinilm")
108108
)
109109

110-
allowlist = read_source("scripts/configs/infiniops_ops.txt")
111-
self.assertNotIn("_infinilm", allowlist)
110+
operator_config = read_source("scripts/configs/infiniops_ops.json")
111+
self.assertNotIn("_infinilm", operator_config)
112112

113113
def test_infiniops_adapter_temporaries_keep_owning_tensors(self) -> None:
114114
cases = {
@@ -623,6 +623,18 @@ def test_random_sampling_uses_only_canonical_infiniops(self) -> None:
623623
self.assertIn(sentinel, wrapper)
624624
self.assertIn("base/top_k_top_p_sampling_from_logits.h", adapter)
625625
self.assertIn("infini::ops::TopKTopPSamplingFromLogits::Call", adapter)
626+
self.assertIn("active_implementation_indices", adapter)
627+
self.assertIn("INFINICORE_ASSERT(!indices.empty())", adapter)
628+
self.assertIn("sampling_config.set_implementation_index", adapter)
629+
self.assertRegex(adapter, re.compile(r"Fill::Call\(\s*handle,\s*config,"))
630+
self.assertRegex(adapter, re.compile(r"Mul::Call\(\s*handle,\s*config,"))
631+
self.assertRegex(
632+
adapter,
633+
re.compile(
634+
r"TopKTopPSamplingFromLogits::Call\(\s*handle,"
635+
r"\s*sampling_config,"
636+
),
637+
)
626638
self.assertIn("infini::ops::Fill::Call", adapter)
627639
self.assertIn("infini::ops::Mul::Call", adapter)
628640
self.assertIn("1.0f / temperature", adapter)

0 commit comments

Comments
 (0)