Files
Inbox/系统基座文件/2/2.6/2.6.3 相干处理间隔对齐机制 (CPI Alignment Mechanism).md
2025-12-11 07:24:36 +08:00

7.8 KiB
Raw Permalink Blame History

tags, date created, date modified
tags date created date modified
星期三, 十一月 26日 2025, 10:25:55 晚上 星期三, 十一月 26日 2025, 10:28:06 晚上

2.6.3 相干处理间隔对齐机制 (CPI Alignment Mechanism)


TL;DR

本节确立了 “原地乱序重组 (In-Place Scatter Assembly)” 的基线策略。 利用 脉冲索引 (Pulse Index) 直接计算内存偏移量将网络包数据直接写入预分配的页锁定内存Pinned Memory实现零拷贝组装。配合 “空间/时间双重触发” 的提交机制和 “有限零填充” 的容错策略,在抗网络抖动与保障实时性之间取得平衡。


一、 约束输入与对齐 (Constraints & Alignment)

基于前序章节2.1, 2.2, 2.6.2),我们面临以下硬性约束:

  1. 数据形态
    • 输入UDP JUMBO Frame (9KB)。每个包可能包含 1 个或多个脉冲的回波数据,带有 BatchID (CPI ID) 和 PulseIndex
    • 输出:符合 2.2.6 定义的显存布局 [Channel][Pulse][Range] (Padding 对齐)。
  2. 时序特性
    • 网络抖动Jitter客观存在数据包到达顺序不一定严格均等。
    • 算法要求多普勒处理FFT要求脉冲间隔PRI是均匀的。如果数据包晚到我们不能“等”太久否则会阻塞流水线如果包丢了矩阵就“穿孔”了。
  3. 内存模型:必须在 2.2.1 确立的 MemoryPool(页锁定内存)中直接操作,避免额外的 memcpy

二、 权衡分析与选项呈现 (Trade-off Matrix)

议题 1组装策略 (Assembly Strategy)

选项 A. 顺序追加 + 排序 (Append & Sort) B. 原地乱序重组 (In-Place Scatter) (推荐)
机制 收到一个包就 push_back 到 buffer凑够数量后按 PulseIndex 排序整理内存。 根据包头的 PulseIndex 直接计算目标地址偏移 offset,写入最终位置。
内存拷贝 2 次 (接收 ->临时 Buf->排序后 Buf)。 1 次 (接收 ->最终 Buf)。
乱序容忍 好,但整理开销大。 极佳。先到的包占坑,后到的包填坑,无视顺序。
CPU 开销 高 (排序算法)。 极低 (O(1) 地址计算)。

议题 2CPI 提交触发机制 (Commit Trigger)

选项 A. 严格计数触发 (Strict Count) B. 严格时间触发 (Strict Timer) C. 混合双触发 (Hybrid) (推荐)
机制 必须收齐 N 个脉冲才提交。少一个就死等。 无论收多少,每隔 T 毫秒强制提交一次。 收齐 N 个 OR 首包到达后超时 T_max,满足其一即提交。
实时性 。一个包丢了会导致该 CPI 永远卡死,甚至阻塞后续 CPI。 。可能切断正在传输的完整 CPI。 。既保证了完整性,又防止了死锁。
丢包处理 无法处理。 截断。 自适应。超时未齐则标记为“残缺 CPI”。

议题 3残缺数据处理 (Incomplete Data Policy)

当触发超时提交时CPI 矩阵中会有“空洞”(丢包导致的缺失脉冲)。

选项 A. 整块丢弃 (Drop All) B. 零填充 (Zero Padding) (推荐)
机制 只要不完整,整个 CPI 扔掉。 缺失的脉冲位置填 0强行送入 GPU。
算法影响 断续。航迹会中断,但没噪音。 信噪比下降。FFT 旁瓣升高,可能产生假目标。
工程价值 简单,适合严苛场景。 鲁棒。偶尔丢 1-2 个包不影响大局,通过 CFAR 阈值抑制旁瓣。

三、 基线确立与实施规范

为了在 1GbE 的物理限制下榨干性能,我们确立 B. 原地乱序重组 + C. 混合双触发 为基线。

1. 数据结构:智能 CPI 容器 (AssemblyBuffer)

我们在 DataReceiver 中维护一个“正在组装”的 CPI 池。

struct AssemblyBuffer {
    // 基础元数据
    uint64_t batch_id = 0;
    uint64_t first_packet_time_us = 0; // 首包到达时间 (用于超时判定)
    uint32_t packets_received = 0;     // 已收包计数
    uint32_t total_packets_expected = 0; // 预期总包数 (由波位参数决定)

    // 内存指针 (指向 MemoryPool 中的一块 Pinned Memory)
    // 物理布局严格遵循 [Channel][Pulse][Range]
    Complex* data_ptr = nullptr; 
    
    // 位图 (Bitmap):用于快速标记哪些 Pulse 已经收到了
    // 相比 vector<bool> 更快,且方便检查完整性
    std::bitset<MAX_PULSES_PER_CPI> reception_mask;

    // 状态
    enum State { IDLE, ASSEMBLING, READY, DAMAGED };
    State state = IDLE;
};

2. 原地重组逻辑 (In-Place Assembly Logic)

这是 I/O 线程 的核心循环逻辑:

  1. 接收recvmmsg 收到一个 UDP 包。
  2. 解析:读取包头,获取 BatchID (CPI ID) 和 PulseIndex
  3. 寻址
    • BatchID 是新的,从 MemoryPool 申请一块新 AssemblyBuffer
    • BatchID 已存在,命中缓存。
  4. 计算偏移 (关键)
    • 利用 2.2.6 确定的 Pitch (行对齐步长)。
    • TargetAddr = BufferBase + (PulseIndex * Pitch_Bytes)
  5. 写入:将 UDP Payload 直接 memcpyTargetAddr
    • :这是数据进入系统的唯一一次拷贝
  6. 标记reception_mask.set(PulseIndex)packets_received++

3. 提交与超时策略 (Commit & Timeout)

我们需要一个低频(如 1kHz的检查器可以在 I/O 线程的空闲间隙运行,或由定时器触发):

  • 完整性检查if (packets_received == total_packets_expected) -> 立即提交 (Push to GPU Queue)。
  • 超时检查if (Now() - first_packet_time_us > MAX_JITTER_WINDOW_US) -> 强制提交
    • 基线值MAX_JITTER_WINDOW_US 建议设为 CPI 时长的 10%(例如 CPI 为 5ms则抖动容忍窗为 500us

4. 容错与填充规范

强制提交 发生时(即丢包):

  • 丢包率判定
    • LossRate < 5% (如 128 个脉冲丢了 < 6 个):执行 零填充 (Zero Padding)。将 reception_mask 中为 0 的位置对应的内存置零(memset)。标记数据质量为 DEGRADED
    • LossRate >= 5%整块丢弃。FFT 在缺失大量数据时结果不可信。记录 WARNING 日志。

四、 自我反驳与边界修正 (Self-Rebuttal)

  • 反驳 1:原地乱序重组需要预知 PulseIndex,如果 UDP 包头里没有这个字段怎么办?
    • 修正协议层2.1.2)必须强制要求 FPGA/DPU 打包时带上 PulseIndex。如果前端不可控,则必须在 DataReceiver 维护一个软件计数器,但这会失去抗乱序能力,属于降级方案
  • 反驳 2memset 清零操作在大内存(如 64MB下也是耗时的。
    • 修正:我们使用了 MemoryPool。在归还 Block 时,是否需要清零?不,我们在申请 Block 时不清零,而是依赖全覆盖写入。因此,对于没收到的脉冲,必须显式清零,否则会残留上一个 CPI 的脏数据(鬼影目标)。
    • 优化:只对 reception_mask 为 0 的那些行Pitchmemset,而不是整个 Buffer。

总结2.6.3 基线图谱

维度 核心基线 关键技术点
组装模式 In-Place Scatter (原地乱序) Addr = Base + PulseIdx * PitchO(1) 复杂度。
内存操作 Single Copy (单次拷贝) 从 UDP 接收缓冲区直接到 Pinned Memory。
提交触发 Hybrid (满额即发 / 超时强发) 抖动窗口建议为 CPI 时长的 10%。
容错策略 Conditional Padding (条件填充) 丢包 < 5% 补零;> 5% 丢弃。需显式清除脏数据。