metal : key the fa-vec tuned table by family instead of SKU (#29075)

* key the fa-vec tuned table by family instead of SKU

* fall back to baseline for untuned fa-vec gpu families
This commit is contained in:
YiChen Lv
2026-09-23 19:23:15 +08:00
committed by GitHub
parent 057494f93f
commit ee3ecce05c
4 changed files with 1065 additions and 3947 deletions
-1
View File
@@ -3584,7 +3584,6 @@ int ggml_metal_op_flash_attn_ext(ggml_metal_op_t ctx, int idx) {
auto cfg = use_sparse
? ggml_metal_tuning::fa_vec_baseline_cfg((int) ne00, (int) ne20)
: ggml_metal_tuning::fa_vec_pick(
props_dev->device_id,
props_dev->gpu_family,
(int) op->src[1]->type,
(int) ne00, (int) ne20, // dk, dv (ne00 == dk for FA)
File diff suppressed because it is too large Load Diff
+3 -5
View File
@@ -1,6 +1,5 @@
#pragma once
#include "ggml-metal-device.h" // enum ggml_metal_device_id
#include "ggml.h"
#include <cstdint>
@@ -32,7 +31,7 @@ constexpr int8_t FA_VEC_DOMAIN_DECODE = 0; // ne01 == 1
constexpr int8_t FA_VEC_DOMAIN_BATCH = 1; // ne01 >= 2
struct fa_vec_key_t {
int8_t device_id;
int8_t family;
int8_t dtype;
int16_t dk;
int16_t dv;
@@ -70,8 +69,7 @@ void fa_vec_set_override(fa_vec_cfg_t cfg);
void fa_vec_clear_override();
fa_vec_cfg_t fa_vec_baseline_cfg(int dk, int dv);
// device_id selects a per-SKU row; on a miss, gpu_family (0 if unknown) maps to a representative
// SKU and the table is retried. No match -> baseline.
fa_vec_cfg_t fa_vec_pick(enum ggml_metal_device_id device_id, int gpu_family, int dtype, int dk, int dv, int64_t ne11, int64_t ne01);
// Keyed by Apple GPU family; an untuned family matches no row and gets the baseline.
fa_vec_cfg_t fa_vec_pick(int gpu_family, int dtype, int dk, int dv, int64_t ne11, int64_t ne01);
} // namespace ggml_metal_tuning
+5 -2
View File
@@ -26,10 +26,13 @@ Sweep the grid (6 dtypes x 10 head sizes x 4 KV depths x 9 batch widths; a few h
./build/bin/ggml-metal-tuning fa-vec > fa_vec_rows.txt 2> fa_vec_sweep.log
```
`fa_vec_rows.txt` holds nothing but table rows, ready to paste into `fa_vec_tuned_table`: the min-max-regret target, the aggregate benefit gate, the short-KV drop and the pointwise compression are already applied.
`fa_vec_rows.txt` holds nothing but table rows: the min-max-regret target, the aggregate benefit gate, the short-KV drop and the pointwise compression are already applied.
The rows carry the SKU token the runtime reported, but `fa_vec_tuned_table` is keyed by Apple GPU family, so that column has to be retagged before the rows compile.
Your family number is on the `MTLGPUFamilyApple<N>` line the backend logs at init, near the top of `fa_vec_sweep.log`; `N` is the value, and the `MTLGPUFamilyCommon`/`MTLGPUFamilyMetal` lines beside it are not it.
If your log is the only sweep for that family, its rows become the family's segment; where the family already has rows, post the log and let the two be compared before anything is replaced.
A config represents a bucket only if it is no slower than the baseline config at every point that bucket covers, so a config that wins on average but loses at one batch width leaves its bucket at baseline.
`fa_vec_sweep.log` holds the per-cell timings, bucket coverage, noise floor, any cooldown activity, and every config the no-harm rule refused together with the point that refused it.
Post both: the log is what makes the rows reviewable.
Post both, always: the rows now speak for every device in the family, so the log is what makes them reviewable.
Long sweeps can be split.
`--dtype f16,q4_0` and `--dk 128,192` restrict the grid, and the emitted rows for one `(dtype, head size)` do not depend on the others.