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:
@@ -0,0 +1,68 @@
|
||||
# Compilazione, Profiling e Benchmark
|
||||
|
||||
## 1) Profili build consigliati
|
||||
|
||||
## Debug (correttezza e sicurezza)
|
||||
|
||||
```bash
|
||||
gcc -O0 -g3 -fsanitize=address,undefined -fno-omit-frame-pointer -Wall -Wextra -Wpedantic src/*.c tests/*.c -o app_debug
|
||||
```
|
||||
|
||||
Usare questo profilo per trovare UB, out-of-bounds e bug di lifetime.
|
||||
|
||||
## Release (throughput)
|
||||
|
||||
```bash
|
||||
gcc -O3 -march=native -flto -fno-semantic-interposition -DNDEBUG -Wall -Wextra src/*.c -o app_release
|
||||
```
|
||||
|
||||
Confrontare anche con `clang` sullo stesso workload.
|
||||
|
||||
## Release + PGO (opzionale su workload stabile)
|
||||
|
||||
```bash
|
||||
gcc -O3 -fprofile-generate src/*.c -o app_pgo_gen
|
||||
./app_pgo_gen <input-realistico>
|
||||
gcc -O3 -fprofile-use -fprofile-correction src/*.c -o app_pgo
|
||||
```
|
||||
|
||||
Applicare PGO solo quando il dataset di training è rappresentativo.
|
||||
|
||||
## 2) Misurazione minima
|
||||
|
||||
## Tempo e memoria
|
||||
|
||||
```bash
|
||||
/usr/bin/time -v ./app_release
|
||||
```
|
||||
|
||||
## Benchmark ripetibile
|
||||
|
||||
```bash
|
||||
hyperfine --warmup 3 --runs 20 'python3 script.py' './app_release'
|
||||
```
|
||||
|
||||
Bloccare input, CPU governor e carico macchina durante le run.
|
||||
|
||||
## 3) Profiling CPU
|
||||
|
||||
```bash
|
||||
perf stat ./app_release
|
||||
perf record -g ./app_release
|
||||
perf report
|
||||
```
|
||||
|
||||
Usare `perf report` per confermare hotspot reali prima di ottimizzare.
|
||||
|
||||
## 4) Interpretazione pratica
|
||||
|
||||
- Ridurre prima complessità algoritmica.
|
||||
- Ottimizzare poi memoria/cache.
|
||||
- Applicare infine micro-ottimizzazioni (`inline`, branch hints, unrolling) solo se misurate.
|
||||
|
||||
## 5) Gate di accettazione
|
||||
|
||||
1. Nessun errore sanitizer in debug.
|
||||
2. Equivalenza output su dataset di regressione.
|
||||
3. Speedup ripetibile su target reale.
|
||||
4. Metriche e flag compiler documentati nel risultato.
|
||||
@@ -0,0 +1,61 @@
|
||||
# Architettura Modulare C per Performance
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Definire moduli C che siano allo stesso tempo veloci, testabili e sostituibili.
|
||||
|
||||
## Struttura raccomandata
|
||||
|
||||
```text
|
||||
feature/
|
||||
include/feature.h
|
||||
src/feature.c
|
||||
src/feature_internal.h
|
||||
tests/test_feature.c
|
||||
bench/bench_feature.c
|
||||
```
|
||||
|
||||
## Regole API
|
||||
|
||||
1. Esporre API piccole e stabili in `include/feature.h`.
|
||||
2. Esporre tipi opachi quando lo stato interno non deve trapelare.
|
||||
3. Passare sempre buffer e lunghezze esplicite.
|
||||
4. Evitare allocazioni implicite nascoste nelle funzioni hot-path.
|
||||
5. Restituire codici errore prevedibili.
|
||||
|
||||
Esempio di firma:
|
||||
|
||||
```c
|
||||
feature_status_t feature_process(
|
||||
const uint8_t *restrict in,
|
||||
size_t n,
|
||||
uint8_t *restrict out,
|
||||
size_t out_n);
|
||||
```
|
||||
|
||||
## Separazione responsabilità
|
||||
|
||||
- `feature.c`: implementazione pubblica + validazioni input
|
||||
- `feature_internal.h`: helper statici e dettagli non pubblici
|
||||
- `test_feature.c`: correttezza funzionale e edge case
|
||||
- `bench_feature.c`: metriche throughput/latenza isolate
|
||||
|
||||
## Policy di memoria
|
||||
|
||||
1. Definire ownership nel contratto API.
|
||||
2. Prediligere buffer chiamante-alloca per hot-path.
|
||||
3. Usare allocator personalizzato solo se il profiler mostra contesa o overhead.
|
||||
|
||||
## Policy di concorrenza
|
||||
|
||||
1. Preferire moduli reentrant e senza stato globale.
|
||||
2. Separare stato per thread quando serve parallelismo.
|
||||
3. Evitare lock nel percorso caldo; usare partizionamento dati.
|
||||
|
||||
## Checklist revisione modulo
|
||||
|
||||
1. API minima e coerente.
|
||||
2. Nessun dettaglio interno esportato inutilmente.
|
||||
3. Test e benchmark presenti.
|
||||
4. Input validation chiara e costo minimo.
|
||||
5. Dipendenze inter-modulo ridotte.
|
||||
@@ -0,0 +1,61 @@
|
||||
# Patterns Python -> C (efficienza)
|
||||
|
||||
## 1) Mapping dati: scegliere strutture contigue
|
||||
|
||||
- `list[int/float]` -> buffer contiguo (`int32_t*`, `float*`, `double*`) + `size_t n`
|
||||
- `tuple` a campi fissi -> `struct` con tipi espliciti
|
||||
- `dict` con chiavi piccole/note -> array indicizzato o enum + switch
|
||||
- `set` su dominio ridotto -> bitmap; su dominio ampio -> hash table dedicata
|
||||
|
||||
Pattern consigliato per API:
|
||||
|
||||
```c
|
||||
int kernel_run(const float *restrict in, float *restrict out, size_t n);
|
||||
```
|
||||
|
||||
## 2) Mapping controllo di flusso
|
||||
|
||||
- List comprehension numerica -> loop `for` con output preallocato
|
||||
- `sum(...)` -> accumulatore locale tipizzato
|
||||
- Generator pipeline -> passaggi espliciti su buffer intermedi preallocati
|
||||
- Evitare callback in hot-path quando una chiamata diretta è possibile
|
||||
|
||||
## 3) Mapping semantica numerica
|
||||
|
||||
- Definire policy per `float` vs `double` prima della traduzione
|
||||
- Riprodurre comportamento su NaN/Inf, divisione, modulo e rounding
|
||||
- Isolare conversioni int/float fuori dal loop caldo
|
||||
|
||||
## 4) Gestione memoria e ownership
|
||||
|
||||
- Definire ownership in firma funzione e commento API
|
||||
- Evitare `malloc/free` per elemento o per iterazione
|
||||
- Riusare arena/buffer quando il workload è batch
|
||||
- Validare dimensioni e puntatori in ingresso all'inizio della funzione
|
||||
|
||||
## 5) Branch e cache locality
|
||||
|
||||
- Ordinare il branch con caso frequente nel percorso lineare
|
||||
- Ridurre dipendenze dati tra iterazioni in loop lunghi
|
||||
- Ordinare campi `struct` per ridurre padding e cache miss
|
||||
|
||||
## 6) Error model coerente
|
||||
|
||||
Pattern consigliato:
|
||||
|
||||
```c
|
||||
typedef enum {
|
||||
KERNEL_OK = 0,
|
||||
KERNEL_ERR_NULL = 1,
|
||||
KERNEL_ERR_SIZE = 2
|
||||
} kernel_status_t;
|
||||
```
|
||||
|
||||
Restituire errori prevedibili e senza side effect parziali non documentati.
|
||||
|
||||
## 7) Sequenza pratica di traduzione
|
||||
|
||||
1. Portare codice 1:1 in C per equivalenza funzionale.
|
||||
2. Inserire test di parità output.
|
||||
3. Profilare la versione C.
|
||||
4. Ottimizzare solo le funzioni che dominano runtime.
|
||||
Reference in New Issue
Block a user