#!/usr/bin/env python3 """Convert interp_lb_profile.bin to a C header for compile-time embedding.""" import struct, sys if len(sys.argv) < 3: print(f"Usage: {sys.argv[0]} ") sys.exit(1) with open(sys.argv[1], 'rb') as f: magic, version, nprocs, num_heavy = struct.unpack('IIii', f.read(16)) threshold = struct.unpack('d', f.read(8))[0] times = list(struct.unpack(f'{nprocs}d', f.read(nprocs * 8))) heavy = list(struct.unpack(f'{num_heavy}i', f.read(num_heavy * 4))) # For each heavy rank, compute split: left half -> lighter neighbor, right half -> heavy rank # (or vice versa depending on which neighbor is lighter) splits = [] for hr in heavy: prev_t = times[hr - 1] if hr > 0 else 1e30 next_t = times[hr + 1] if hr < nprocs - 1 else 1e30 if prev_t <= next_t: splits.append((hr, hr - 1, hr)) # (block_id, r_left, r_right) else: splits.append((hr, hr, hr + 1)) # Also remap the displaced neighbor blocks remaps = {} for hr, r_l, r_r in splits: if r_l != hr: # We took r_l's slot, so remap block r_l to its other neighbor displaced = r_l if displaced > 0 and displaced - 1 not in [s[0] for s in splits]: remaps[displaced] = displaced - 1 elif displaced < nprocs - 1: remaps[displaced] = displaced + 1 else: displaced = r_r if displaced < nprocs - 1 and displaced + 1 not in [s[0] for s in splits]: remaps[displaced] = displaced + 1 elif displaced > 0: remaps[displaced] = displaced - 1 with open(sys.argv[2], 'w') as out: out.write("/* Auto-generated from interp_lb_profile.bin — do not edit */\n") out.write("#ifndef INTERP_LB_PROFILE_DATA_H\n") out.write("#define INTERP_LB_PROFILE_DATA_H\n\n") out.write(f"#define INTERP_LB_NPROCS {nprocs}\n") out.write(f"#define INTERP_LB_NUM_HEAVY {num_heavy}\n\n") out.write(f"static const int interp_lb_heavy_blocks[{num_heavy}] = {{") out.write(", ".join(str(h) for h in heavy)) out.write("};\n\n") out.write("/* Split table: {block_id, r_left, r_right} */\n") out.write(f"static const int interp_lb_splits[{num_heavy}][3] = {{\n") for bid, rl, rr in splits: out.write(f" {{{bid}, {rl}, {rr}}},\n") out.write("};\n\n") out.write("/* Rank remap for displaced neighbor blocks */\n") out.write(f"static const int interp_lb_num_remaps = {len(remaps)};\n") out.write(f"static const int interp_lb_remaps[][2] = {{\n") for src, dst in sorted(remaps.items()): out.write(f" {{{src}, {dst}}},\n") if not remaps: out.write(" {-1, -1},\n") out.write("};\n\n") out.write("#endif /* INTERP_LB_PROFILE_DATA_H */\n") print(f"Generated {sys.argv[2]}:") print(f" {num_heavy} heavy blocks to split: {heavy}") for bid, rl, rr in splits: print(f" block {bid}: split -> rank {rl} (left), rank {rr} (right)") for src, dst in sorted(remaps.items()): print(f" block {src}: remap -> rank {dst}")