Procházet zdrojové kódy

feat: cap refinement plan by max concurrent

master
Jan Svabenik před 18 hodinami
rodič
revize
da90fa9f53
3 změnil soubory, kde provedl 62 přidání a 40 odebrání
  1. +40
    -38
      internal/pipeline/policy.go
  2. +6
    -2
      internal/pipeline/scheduler.go
  3. +16
    -0
      internal/pipeline/scheduler_test.go

+ 40
- 38
internal/pipeline/policy.go Zobrazit soubor

@@ -3,48 +3,50 @@ package pipeline
import "sdr-wideband-suite/internal/config"

type Policy struct {
Mode string `json:"mode"`
Intent string `json:"intent"`
MonitorStartHz float64 `json:"monitor_start_hz,omitempty"`
MonitorEndHz float64 `json:"monitor_end_hz,omitempty"`
MonitorSpanHz float64 `json:"monitor_span_hz,omitempty"`
SignalPriorities []string `json:"signal_priorities,omitempty"`
AutoRecordClasses []string `json:"auto_record_classes,omitempty"`
AutoDecodeClasses []string `json:"auto_decode_classes,omitempty"`
SurveillanceFFTSize int `json:"surveillance_fft_size"`
SurveillanceFPS int `json:"surveillance_fps"`
DisplayBins int `json:"display_bins"`
DisplayFPS int `json:"display_fps"`
RefinementEnabled bool `json:"refinement_enabled"`
MaxRefinementJobs int `json:"max_refinement_jobs"`
MinCandidateSNRDb float64 `json:"min_candidate_snr_db"`
RefinementMinSpanHz float64 `json:"refinement_min_span_hz"`
RefinementMaxSpanHz float64 `json:"refinement_max_span_hz"`
RefinementAutoSpan bool `json:"refinement_auto_span"`
PreferGPU bool `json:"prefer_gpu"`
Mode string `json:"mode"`
Intent string `json:"intent"`
MonitorStartHz float64 `json:"monitor_start_hz,omitempty"`
MonitorEndHz float64 `json:"monitor_end_hz,omitempty"`
MonitorSpanHz float64 `json:"monitor_span_hz,omitempty"`
SignalPriorities []string `json:"signal_priorities,omitempty"`
AutoRecordClasses []string `json:"auto_record_classes,omitempty"`
AutoDecodeClasses []string `json:"auto_decode_classes,omitempty"`
SurveillanceFFTSize int `json:"surveillance_fft_size"`
SurveillanceFPS int `json:"surveillance_fps"`
DisplayBins int `json:"display_bins"`
DisplayFPS int `json:"display_fps"`
RefinementEnabled bool `json:"refinement_enabled"`
MaxRefinementJobs int `json:"max_refinement_jobs"`
RefinementMaxConcurrent int `json:"refinement_max_concurrent"`
MinCandidateSNRDb float64 `json:"min_candidate_snr_db"`
RefinementMinSpanHz float64 `json:"refinement_min_span_hz"`
RefinementMaxSpanHz float64 `json:"refinement_max_span_hz"`
RefinementAutoSpan bool `json:"refinement_auto_span"`
PreferGPU bool `json:"prefer_gpu"`
}

func PolicyFromConfig(cfg config.Config) Policy {
return Policy{
Mode: cfg.Pipeline.Mode,
Intent: cfg.Pipeline.Goals.Intent,
MonitorStartHz: cfg.Pipeline.Goals.MonitorStartHz,
MonitorEndHz: cfg.Pipeline.Goals.MonitorEndHz,
MonitorSpanHz: cfg.Pipeline.Goals.MonitorSpanHz,
SignalPriorities: append([]string(nil), cfg.Pipeline.Goals.SignalPriorities...),
AutoRecordClasses: append([]string(nil), cfg.Pipeline.Goals.AutoRecordClasses...),
AutoDecodeClasses: append([]string(nil), cfg.Pipeline.Goals.AutoDecodeClasses...),
SurveillanceFFTSize: cfg.Surveillance.AnalysisFFTSize,
SurveillanceFPS: cfg.Surveillance.FrameRate,
DisplayBins: cfg.Surveillance.DisplayBins,
DisplayFPS: cfg.Surveillance.DisplayFPS,
RefinementEnabled: cfg.Refinement.Enabled,
MaxRefinementJobs: cfg.Resources.MaxRefinementJobs,
MinCandidateSNRDb: cfg.Refinement.MinCandidateSNRDb,
RefinementMinSpanHz: cfg.Refinement.MinSpanHz,
RefinementMaxSpanHz: cfg.Refinement.MaxSpanHz,
RefinementAutoSpan: config.BoolValue(cfg.Refinement.AutoSpan, true),
PreferGPU: cfg.Resources.PreferGPU,
Mode: cfg.Pipeline.Mode,
Intent: cfg.Pipeline.Goals.Intent,
MonitorStartHz: cfg.Pipeline.Goals.MonitorStartHz,
MonitorEndHz: cfg.Pipeline.Goals.MonitorEndHz,
MonitorSpanHz: cfg.Pipeline.Goals.MonitorSpanHz,
SignalPriorities: append([]string(nil), cfg.Pipeline.Goals.SignalPriorities...),
AutoRecordClasses: append([]string(nil), cfg.Pipeline.Goals.AutoRecordClasses...),
AutoDecodeClasses: append([]string(nil), cfg.Pipeline.Goals.AutoDecodeClasses...),
SurveillanceFFTSize: cfg.Surveillance.AnalysisFFTSize,
SurveillanceFPS: cfg.Surveillance.FrameRate,
DisplayBins: cfg.Surveillance.DisplayBins,
DisplayFPS: cfg.Surveillance.DisplayFPS,
RefinementEnabled: cfg.Refinement.Enabled,
MaxRefinementJobs: cfg.Resources.MaxRefinementJobs,
RefinementMaxConcurrent: cfg.Refinement.MaxConcurrent,
MinCandidateSNRDb: cfg.Refinement.MinCandidateSNRDb,
RefinementMinSpanHz: cfg.Refinement.MinSpanHz,
RefinementMaxSpanHz: cfg.Refinement.MaxSpanHz,
RefinementAutoSpan: config.BoolValue(cfg.Refinement.AutoSpan, true),
PreferGPU: cfg.Resources.PreferGPU,
}
}



+ 6
- 2
internal/pipeline/scheduler.go Zobrazit soubor

@@ -11,10 +11,14 @@ type ScheduledCandidate struct {
// Current heuristic is intentionally simple and deterministic; later phases can add
// richer scoring (novelty, persistence, profile-aware band priorities, decoder value).
func BuildRefinementPlan(candidates []Candidate, policy Policy) RefinementPlan {
budget := policy.MaxRefinementJobs
if policy.RefinementMaxConcurrent > 0 && (budget <= 0 || policy.RefinementMaxConcurrent < budget) {
budget = policy.RefinementMaxConcurrent
}
plan := RefinementPlan{
TotalCandidates: len(candidates),
MinCandidateSNRDb: policy.MinCandidateSNRDb,
Budget: policy.MaxRefinementJobs,
Budget: budget,
}
if len(candidates) == 0 {
return plan
@@ -40,7 +44,7 @@ func BuildRefinementPlan(candidates []Candidate, policy Policy) RefinementPlan {
}
return scored[i].Priority > scored[j].Priority
})
limit := policy.MaxRefinementJobs
limit := plan.Budget
if limit <= 0 || limit > len(scored) {
limit = len(scored)
}


+ 16
- 0
internal/pipeline/scheduler_test.go Zobrazit soubor

@@ -44,6 +44,22 @@ func TestBuildRefinementPlanTracksDrops(t *testing.T) {
}
}

func TestBuildRefinementPlanRespectsMaxConcurrent(t *testing.T) {
policy := Policy{MaxRefinementJobs: 5, RefinementMaxConcurrent: 2, MinCandidateSNRDb: 0}
cands := []Candidate{
{ID: 1, CenterHz: 100, SNRDb: 9},
{ID: 2, CenterHz: 200, SNRDb: 8},
{ID: 3, CenterHz: 300, SNRDb: 7},
}
plan := BuildRefinementPlan(cands, policy)
if plan.Budget != 2 {
t.Fatalf("expected budget 2, got %d", plan.Budget)
}
if len(plan.Selected) != 2 {
t.Fatalf("expected 2 selected, got %d", len(plan.Selected))
}
}

func TestAutoSpanForHint(t *testing.T) {
span, source := AutoSpanForHint("WFM_STEREO")
if span < 150000 || source == "" {


Načítá se…
Zrušit
Uložit