[GH-ISSUE #318] data_placement.py 中使用pyomo建模时的一个约束问题 #196

Open
opened 2026-10-26 09:46:58 +00:00 by bsakaguchi · 3 comments
Owner

Originally created by @Siannochan on GitHub (Jul 28, 2025).
Original GitHub issue: https://github.com/deepseek-ai/3FS/issues/318

问题复现

首先按照 README 中提供的参数,执行 data_placement.py 生成一个解:

-ql -relax -type CR -v 5 -min_r 6 -k 3 -j 1

再对这个解添加一个节点,尝试利用 RebalanceTrafficModel 生成一个新的解:

-ql -relax -type CR -v 6 -min_r 6 -k 3 -j 1 -m output\DataPlacementModel-v_5-b_10-r_6-k_3-λ_2-lb_1-ub_1\incidence_matrix.pickle

此时 check_solution 报错:

AssertionError: peer_traffic=0.5 < self.max_recovery_traffic_on_peer=2 - 1

原因分析

在 chain_table_type="CR" 时 λ(也即 max_recovery_traffic_on_peer)被定义为 r / (v - 1),这与 BIBD 中的 λ = r * (k-1) / (v-1) 不同(为什么要这样定义?)。在 pyomo建立模型时,对于 peer_recovery_traffic 的计算相当于 λ 在 BIBD 中的定义,而其上下限约束则使用了 r / (v - 1) 这个定义,因此提供的约束条件会与预期不符。我不确定这是 bug 还是我错误理解,但我尝试修改了代码以使得约束与预期一致。如果确为 bug 我再提 PR。

修改约束

#修改前
def peer_recovery_traffic_upper_bound(model, disk, peer):
  if self.balanced_incomplete_block_design:
    return calc_peer_recovery_traffic(model, disk, peer) == self.max_recovery_traffic_on_peer
  else:
    return calc_peer_recovery_traffic(model, disk, peer) <= self.max_recovery_traffic_on_peer + self.relax_ub
model.peer_recovery_traffic_upper_bound_eqn = po.Constraint(model.disk_pairs, rule=peer_recovery_traffic_upper_bound)

def peer_recovery_traffic_lower_bound(model, disk, peer):
  return calc_peer_recovery_traffic(model, disk, peer) >= max(0, self.max_recovery_traffic_on_peer - self.relax_lb)

# 修改后
def peer_recovery_traffic_upper_bound(model, disk, peer):
  if self.balanced_incomplete_block_design:
    return calc_peer_recovery_traffic(model, disk, peer) == self.max_recovery_traffic_on_peer / self.recovery_traffic_factor * (self.group_size - 1)
  else:
    return calc_peer_recovery_traffic(model, disk, peer) <= (self.max_recovery_traffic_on_peer + self.relax_ub) / self.recovery_traffic_factor * (self.group_size - 1)
model.peer_recovery_traffic_upper_bound_eqn = po.Constraint(model.disk_pairs, rule=peer_recovery_traffic_upper_bound)

def peer_recovery_traffic_lower_bound(model, disk, peer):
  return calc_peer_recovery_traffic(model, disk, peer) >= max(0, self.max_recovery_traffic_on_peer - self.relax_lb) / self.recovery_traffic_factor * (self.group_size - 1)
Originally created by @Siannochan on GitHub (Jul 28, 2025). Original GitHub issue: https://github.com/deepseek-ai/3FS/issues/318 #### 问题复现 首先按照 README 中提供的参数,执行 data_placement.py 生成一个解: ``` -ql -relax -type CR -v 5 -min_r 6 -k 3 -j 1 ``` 再对这个解添加一个节点,尝试利用 RebalanceTrafficModel 生成一个新的解: ``` -ql -relax -type CR -v 6 -min_r 6 -k 3 -j 1 -m output\DataPlacementModel-v_5-b_10-r_6-k_3-λ_2-lb_1-ub_1\incidence_matrix.pickle ``` 此时 check_solution 报错: ``` AssertionError: peer_traffic=0.5 < self.max_recovery_traffic_on_peer=2 - 1 ``` #### 原因分析 在 chain_table_type="CR" 时 λ(也即 max_recovery_traffic_on_peer)被定义为 r / (v - 1),这与 BIBD 中的 λ = r * (k-1) / (v-1) 不同(为什么要这样定义?)。在 pyomo建立模型时,对于 peer_recovery_traffic 的计算相当于 λ 在 BIBD 中的定义,而其上下限约束则使用了 r / (v - 1) 这个定义,因此提供的约束条件会与预期不符。我不确定这是 bug 还是我错误理解,但我尝试修改了代码以使得约束与预期一致。如果确为 bug 我再提 PR。 #### 修改约束 ``` #修改前 def peer_recovery_traffic_upper_bound(model, disk, peer): if self.balanced_incomplete_block_design: return calc_peer_recovery_traffic(model, disk, peer) == self.max_recovery_traffic_on_peer else: return calc_peer_recovery_traffic(model, disk, peer) <= self.max_recovery_traffic_on_peer + self.relax_ub model.peer_recovery_traffic_upper_bound_eqn = po.Constraint(model.disk_pairs, rule=peer_recovery_traffic_upper_bound) def peer_recovery_traffic_lower_bound(model, disk, peer): return calc_peer_recovery_traffic(model, disk, peer) >= max(0, self.max_recovery_traffic_on_peer - self.relax_lb) # 修改后 def peer_recovery_traffic_upper_bound(model, disk, peer): if self.balanced_incomplete_block_design: return calc_peer_recovery_traffic(model, disk, peer) == self.max_recovery_traffic_on_peer / self.recovery_traffic_factor * (self.group_size - 1) else: return calc_peer_recovery_traffic(model, disk, peer) <= (self.max_recovery_traffic_on_peer + self.relax_ub) / self.recovery_traffic_factor * (self.group_size - 1) model.peer_recovery_traffic_upper_bound_eqn = po.Constraint(model.disk_pairs, rule=peer_recovery_traffic_upper_bound) def peer_recovery_traffic_lower_bound(model, disk, peer): return calc_peer_recovery_traffic(model, disk, peer) >= max(0, self.max_recovery_traffic_on_peer - self.relax_lb) / self.recovery_traffic_factor * (self.group_size - 1) ```
Author
Owner

@wlxiong commented on GitHub (Jul 28, 2025):

最早的设计里, 在扩容时 (即增加nodes) 可以通过RebalanceTrafficModel计算迁移流量最小的新数据放置方案. 但是后来没有实现扩容现有集群这个功能, 所以RebalanceTrafficModel可以认为是被废弃了.

<!-- gh-comment-id:3126269975 --> @wlxiong commented on GitHub (Jul 28, 2025): 最早的设计里, 在扩容时 (即增加nodes) 可以通过RebalanceTrafficModel计算迁移流量最小的新数据放置方案. 但是后来没有实现扩容现有集群这个功能, 所以RebalanceTrafficModel可以认为是被废弃了.
Author
Owner

@Siannochan commented on GitHub (Jul 28, 2025):

最早的设计里, 在扩容时 (即增加nodes) 可以通过RebalanceTrafficModel计算迁移流量最小的新数据放置方案. 但是后来没有实现扩容现有集群这个功能, 所以RebalanceTrafficModel可以认为是被废弃了.

好的。但如果我想实现扩容,也还是可以使用 RebalanceTrafficModel 生成新的 chain_table,并手动迁移相关数据对吧?

<!-- gh-comment-id:3126393849 --> @Siannochan commented on GitHub (Jul 28, 2025): > 最早的设计里, 在扩容时 (即增加nodes) 可以通过RebalanceTrafficModel计算迁移流量最小的新数据放置方案. 但是后来没有实现扩容现有集群这个功能, 所以RebalanceTrafficModel可以认为是被废弃了. 好的。但如果我想实现扩容,也还是可以使用 RebalanceTrafficModel 生成新的 chain_table,并手动迁移相关数据对吧?
Author
Owner

@Siannochan commented on GitHub (Jul 28, 2025):

而且事实上,上面这个问题不仅是扩容时会影响,正常创建一个新的放置方案,在有些参数情况下也会暴露问题,比如:

-ql -relax -type CR -v 8 -min_r 8 -k 3

会报同样的错误,因为本质上是 DataPlacementModel 中 build_model() 里的约束问题,与 RebalanceTrafficModel 没有直接联系。

<!-- gh-comment-id:3126449156 --> @Siannochan commented on GitHub (Jul 28, 2025): 而且事实上,上面这个问题不仅是扩容时会影响,正常创建一个新的放置方案,在有些参数情况下也会暴露问题,比如: ``` -ql -relax -type CR -v 8 -min_r 8 -k 3 ``` 会报同样的错误,因为本质上是 DataPlacementModel 中 build_model() 里的约束问题,与 RebalanceTrafficModel 没有直接联系。
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
deepseek-ai/3FS#196
No description provided.