feat(skills): add local python-to-c-efficiency skill with modular C scaffold
add local Codex skill for Python->C performance-focused translation define modular C architecture and benchmark/correctness gates add references for patterns, profiling, and module design add scaffold_c_module.py to generate include/src/tests/bench skeleton update agent default prompt for benchmark-backed optimizations
This commit is contained in:
201
.codex/skills/python-to-c-efficiency/scripts/scaffold_c_module.py
Executable file
201
.codex/skills/python-to-c-efficiency/scripts/scaffold_c_module.py
Executable file
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate a performance-oriented C module skeleton.
|
||||
|
||||
Creates:
|
||||
- include/<name>.h
|
||||
- src/<name>.c
|
||||
- tests/test_<name>.c
|
||||
- bench/bench_<name>.c
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def normalize_name(raw: str) -> str:
|
||||
name = raw.strip().lower().replace("-", "_")
|
||||
name = re.sub(r"[^a-z0-9_]", "_", name)
|
||||
name = re.sub(r"_+", "_", name).strip("_")
|
||||
if not name:
|
||||
raise ValueError("module name is empty after normalization")
|
||||
if name[0].isdigit():
|
||||
name = f"m_{name}"
|
||||
return name
|
||||
|
||||
|
||||
def write_file(path: Path, content: str, force: bool) -> None:
|
||||
if path.exists() and not force:
|
||||
raise FileExistsError(f"file exists: {path}")
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(content, encoding="utf-8")
|
||||
|
||||
|
||||
def render_header(module: str) -> str:
|
||||
guard = f"{module.upper()}_H"
|
||||
return f"""#ifndef {guard}
|
||||
#define {guard}
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {{
|
||||
#endif
|
||||
|
||||
typedef enum {{
|
||||
{module}_ok = 0,
|
||||
{module}_err_null = 1,
|
||||
{module}_err_size = 2
|
||||
}} {module}_status_t;
|
||||
|
||||
{module}_status_t {module}_process_f32(
|
||||
const float *restrict in,
|
||||
float *restrict out,
|
||||
size_t n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
"""
|
||||
|
||||
|
||||
def render_source(module: str) -> str:
|
||||
return f"""#include "{module}.h"
|
||||
|
||||
{module}_status_t {module}_process_f32(
|
||||
const float *restrict in,
|
||||
float *restrict out,
|
||||
size_t n)
|
||||
{{
|
||||
if (in == NULL || out == NULL) {{
|
||||
return {module}_err_null;
|
||||
}}
|
||||
if (n == 0) {{
|
||||
return {module}_err_size;
|
||||
}}
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {{
|
||||
out[i] = in[i] * 1.0f;
|
||||
}}
|
||||
|
||||
return {module}_ok;
|
||||
}}
|
||||
"""
|
||||
|
||||
|
||||
def render_test(module: str) -> str:
|
||||
return f"""#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "{module}.h"
|
||||
|
||||
int main(void)
|
||||
{{
|
||||
float in[4] = {{1.0f, 2.0f, 3.0f, 4.0f}};
|
||||
float out[4] = {{0.0f, 0.0f, 0.0f, 0.0f}};
|
||||
|
||||
{module}_status_t st = {module}_process_f32(in, out, 4);
|
||||
assert(st == {module}_ok);
|
||||
for (size_t i = 0; i < 4; ++i) {{
|
||||
assert(out[i] == in[i]);
|
||||
}}
|
||||
|
||||
printf("test_{module}: ok\\n");
|
||||
return 0;
|
||||
}}
|
||||
"""
|
||||
|
||||
|
||||
def render_bench(module: str) -> str:
|
||||
return f"""#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "{module}.h"
|
||||
|
||||
static uint64_t ns_now(void)
|
||||
{{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (uint64_t)ts.tv_sec * 1000000000ull + (uint64_t)ts.tv_nsec;
|
||||
}}
|
||||
|
||||
int main(void)
|
||||
{{
|
||||
const size_t n = 1u << 20;
|
||||
float *in = (float *)malloc(n * sizeof(float));
|
||||
float *out = (float *)malloc(n * sizeof(float));
|
||||
if (!in || !out) {{
|
||||
fprintf(stderr, "alloc failed\\n");
|
||||
free(in);
|
||||
free(out);
|
||||
return 1;
|
||||
}}
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {{
|
||||
in[i] = (float)(i & 1023u);
|
||||
}}
|
||||
|
||||
uint64_t t0 = ns_now();
|
||||
{module}_status_t st = {module}_process_f32(in, out, n);
|
||||
uint64_t t1 = ns_now();
|
||||
if (st != {module}_ok) {{
|
||||
fprintf(stderr, "kernel error: %d\\n", (int)st);
|
||||
free(in);
|
||||
free(out);
|
||||
return 1;
|
||||
}}
|
||||
|
||||
double ns_per_elem = (double)(t1 - t0) / (double)n;
|
||||
printf("{module} ns/elem: %.3f\\n", ns_per_elem);
|
||||
|
||||
free(in);
|
||||
free(out);
|
||||
return 0;
|
||||
}}
|
||||
"""
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Scaffold a C module with tests and bench")
|
||||
parser.add_argument("--name", required=True, help="Module name (snake_case preferred)")
|
||||
parser.add_argument(
|
||||
"--out-dir",
|
||||
default=".",
|
||||
help="Project root where include/src/tests/bench live",
|
||||
)
|
||||
parser.add_argument("--force", action="store_true", help="Overwrite existing files")
|
||||
args = parser.parse_args()
|
||||
|
||||
module = normalize_name(args.name)
|
||||
root = Path(args.out_dir).resolve()
|
||||
|
||||
write_file(root / "include" / f"{module}.h", render_header(module), args.force)
|
||||
write_file(root / "src" / f"{module}.c", render_source(module), args.force)
|
||||
write_file(root / "tests" / f"test_{module}.c", render_test(module), args.force)
|
||||
write_file(root / "bench" / f"bench_{module}.c", render_bench(module), args.force)
|
||||
|
||||
print(f"created module skeleton: {module}")
|
||||
print(f"root: {root}")
|
||||
print("next:")
|
||||
print(
|
||||
f" gcc -O0 -g3 -fsanitize=address,undefined "
|
||||
f"-Iinclude src/{module}.c tests/test_{module}.c -o test_{module}"
|
||||
)
|
||||
print(
|
||||
f" gcc -O3 -march=native "
|
||||
f"-Iinclude src/{module}.c bench/bench_{module}.c -o bench_{module}"
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user