C COMPIN BLOG

COMPIN TECHNICAL NOTE

新手教材(7/13)|第七编:SPP、图像 Tile 与部分成功

解码 SPP 头、Tile、Morton 顺序、对象窗口和部分成功,并说明有状态算子与动态路径的理论张力。

本文是《从 IP 到 SRv6 计算编排》新手教材第 7/13 编。 总目录 · 上一篇:第六编:Anycast 从逻辑服务选择实例 · 下一篇:第八编:链路变差时的三级自主降档

48. SPP是什么

**SPP(Satellite Processing Protocol,卫星处理协议)**是本项目为图像Tile定义的业务层 二进制协议。它不是IPv6扩展头,不是SRH,也不是控制面消息。

各层关系是:

Ethernet
└── IPv6
    └── SRH
        └── UDP或项目承载
            └── SPP header
                └── RGB/Gray/Edge payload

IPv6/SRH负责“包经过哪里”,SPP负责“包里面是哪一个任务、对象、Tile和图像格式”。算子只 在验证外层边界后读取SPP。

49. 为什么不直接发送一整张图片

把图片切成Tile有四个好处:

  1. 单包大小受MTU约束,Tile便于控制包长;
  2. 不同Tile可流水并行,而不必等整张图;
  3. 丢失影响可局部量化;
  4. 算子可按Tile或邻域逐步产生输出。

代价是系统必须显式管理对象身份、Tile坐标、epoch和不完整窗口。SPP正是为这些语义提供 共同契约。

50. SPP 64-byte固定头

当前头长固定为64 byte。多字节整数按网络字节序编码。

字节偏移字段长度含义
0magic4固定魔数,用于识别SPP
4version1协议版本
5header_length1头长度,当前为64
6dimensions1维度信息
7payload_format1RGB24、GRAY8或EDGE1
8flags2标志位
10payload_length2SPP负载字节数
12task_id8任务身份,必须非零
20object_id8对象身份,必须非零
28tile_id8Tile的Morton编码
36original_width4原对象宽度
40original_height4原对象高度
44tile_width2当前Tile宽度
46tile_height2当前Tile高度
48grid_columns2Tile网格列数
50grid_rows2Tile网格行数
52object_epoch4同一object的新版本序号
56reserved8保留,供协议演进

接收者必须先验证magic、version、header length、payload length与实际帧边界,再访问后续 字段。不能因为以太网帧“看起来够长”就假定里面一定是合法SPP。

51. 三个身份字段不能相互替代

51.1 task_id

表示这份数据属于哪一次计算编排。相同图片同时进入两个不同DAG时,task_id不同,缓存也 必须分开。

51.2 object_id

表示任务内的哪一个逻辑对象,例如第42张图。一个task可连续处理许多object。

51.3 object_epoch

表示同一个object的哪一版。对象被重新采集、重传或更新时epoch增加。旧epoch迟到,不能 污染新epoch的窗口。

因此正确缓存键是:

(task_id, object_id, object_epoch)

只用task会把整条业务的所有图片混在一起;只用object会把不同任务和版本混在一起;用 五元组也不够,因为路径变化后五元组可能变化,而业务身份没有变化。

52. Morton编码

**Morton Code(莫顿码,又称Z-order curve,Z序曲线)**把二维坐标的二进制位交错成一个 整数,使空间相近的Tile通常仍有接近的编号。

若x和y的低位分别为:

x = ... x2 x1 x0
y = ... y2 y1 y0

则Morton码交错为:

... y2 x2 y1 x1 y0 x0

例如x=2即二进制10,y=1即01:

x位:x1=1, x0=0
y位:y1=0, y0=1
交错:y1 x1 y0 x0 = 0 1 1 0 = 6

算子不能把tile_id+1简单理解成“右边一块”。必须先Morton decode(解码)得到(x,y), 检查grid_columns/grid_rows,再计算邻域。

53. 包、Tile、窗口和任务不是同一个成功单位

这四层需要分别计数:

  • 包成功:某个网络包到达下一处理点;
  • Tile成功:某个Tile完成要求的算子链并到达目的端;
  • 对象窗口完整:某个有状态算子收到其计算所需的Tile集合;
  • 任务结果:任务观察期内所有预期Tile的完成比例。

若预期100个Tile,最终有90个完成,则该任务是90%成功,不是“任务失败”。公式为:

task_success_ratio = completed_expected_tiles / total_expected_tiles

只有协议或实验定义明确要求all-or-nothing(全有或全无)时,才可把任一Tile丢失折算成整个 task失败。本项目对SPP采用可量化的部分成功语义。

这也解释了为什么“不完整窗口被丢弃”是局部损失证据,而不是自动宣判整条任务为0。

54. SPP与Anycast的根本张力

无状态算子使用Anycast很自然:每个Tile无论落到哪个同类型实例,都得到相同结果。

有状态算子不同。假设一个2×2 group的四个Tile经逻辑Anycast服务转发:

tile A、B → Mean@node-20
tile C、D → Mean@node-44

两个实例都只看见半个group,都会等待并最终超时。网络没有丢包,但应用状态被拆散了。 这不是“Anycast把一个包复制到五个容器”,而是不同包在不同时刻根据当时FIB选择了不同 provider。

可以引入会话粘性、共享状态或一致性哈希,但这些都形成新的系统机制和研究问题。当前不应 为了某个测试结果临时写“同task永远绑死某节点”的补丁。教材中的正确结论是:

  • SPP可以与Exact或Resilient结合;
  • 有状态算子在provider漂移时天然可能产生窗口损失;
  • 该损失按Tile完成比例计入可靠性;
  • 更高层的状态安置理论留给后续研究;
  • 观测必须保留完整身份,才能量化损失来自何处。

总目录 · 上一篇:第六编:Anycast 从逻辑服务选择实例 · 下一篇:第八编:链路变差时的三级自主降档