Skip to content

Commit 6d78159

Browse files
committed
reuse block key work in transport hot path
1 parent 270ad49 commit 6d78159

4 files changed

Lines changed: 70 additions & 5 deletions

File tree

src/core/energy.zig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,20 @@ pub fn pairWeight(comptime T: type, left: T, right: T, cfg: Config) u64 {
55
return 1 + key.closenessBonus(T, left, right, cfg);
66
}
77

8+
pub fn pairWeightFromKeys(comptime T: type, left_key: key.KeyType(T), right_key: key.KeyType(T), cfg: Config) u64 {
9+
return 1 + key.closenessBonusFromKeys(T, left_key, right_key, cfg);
10+
}
11+
812
pub fn pairEnergy(comptime T: type, left: T, right: T, cfg: Config) u64 {
913
if (!key.greaterThan(T, left, right)) return 0;
1014
return pairWeight(T, left, right, cfg);
1115
}
1216

17+
pub fn pairEnergyFromKeys(comptime T: type, left_key: key.KeyType(T), right_key: key.KeyType(T), cfg: Config) u64 {
18+
if (!key.greaterThanKeys(T, left_key, right_key)) return 0;
19+
return pairWeightFromKeys(T, left_key, right_key, cfg);
20+
}
21+
1322
pub fn blockEnergy(comptime T: type, xs: []const T, cfg: Config) u64 {
1423
var total: u64 = 0;
1524
for (xs, 0..) |left, i| {
@@ -20,3 +29,14 @@ pub fn blockEnergy(comptime T: type, xs: []const T, cfg: Config) u64 {
2029
}
2130
return total;
2231
}
32+
33+
pub fn blockEnergyFromKeys(comptime T: type, keys: []const key.KeyType(T), cfg: Config) u64 {
34+
var total: u64 = 0;
35+
for (keys, 0..) |left_key, i| {
36+
var j = i + 1;
37+
while (j < keys.len) : (j += 1) {
38+
total += pairEnergyFromKeys(T, left_key, keys[j], cfg);
39+
}
40+
}
41+
return total;
42+
}

src/core/key.zig

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ const std = @import("std");
22
const Config = @import("config.zig").Config;
33
const types = @import("types.zig");
44

5+
pub const KeyType = types.UnsignedOf;
6+
57
pub fn biasedKey(comptime T: type, value: T) types.UnsignedOf(T) {
68
const info = @typeInfo(T);
79
const U = types.UnsignedOf(T);
@@ -20,8 +22,12 @@ pub fn biasedKey(comptime T: type, value: T) types.UnsignedOf(T) {
2022
}
2123

2224
pub fn closenessBonus(comptime T: type, left: T, right: T, cfg: Config) u8 {
25+
return closenessBonusFromKeys(T, biasedKey(T, left), biasedKey(T, right), cfg);
26+
}
27+
28+
pub fn closenessBonusFromKeys(comptime T: type, left_key: types.UnsignedOf(T), right_key: types.UnsignedOf(T), cfg: Config) u8 {
2329
const U = types.UnsignedOf(T);
24-
const diff: U = biasedKey(T, left) ^ biasedKey(T, right);
30+
const diff: U = left_key ^ right_key;
2531
if (diff == 0) return cfg.valuation_cap;
2632

2733
const tz: usize = @ctz(diff);
@@ -37,3 +43,7 @@ pub fn compare(comptime T: type, left: T, right: T) std.math.Order {
3743
pub fn greaterThan(comptime T: type, left: T, right: T) bool {
3844
return left > right;
3945
}
46+
47+
pub fn greaterThanKeys(comptime T: type, left_key: types.UnsignedOf(T), right_key: types.UnsignedOf(T)) bool {
48+
return left_key > right_key;
49+
}

src/core/pressure.zig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,29 @@ pub fn compute(comptime T: type, block: []const T, cfg: Config, pressures: []i32
3030
}
3131
}
3232

33+
pub fn computeFromKeys(comptime T: type, keys: []const key.KeyType(T), cfg: Config, pressures: []i32) void {
34+
std.debug.assert(pressures.len >= keys.len);
35+
36+
@memset(pressures[0..keys.len], 0);
37+
if (keys.len <= 1) return;
38+
39+
for (keys, 0..) |left_key, i| {
40+
const end = @min(keys.len, i + cfg.neighborhood + 1);
41+
var j = i + 1;
42+
while (j < end) : (j += 1) {
43+
const right_key = keys[j];
44+
if (left_key > right_key) {
45+
const w: i32 = @intCast(energy.pairWeightFromKeys(T, left_key, right_key, cfg));
46+
pressures[i] += w;
47+
pressures[j] -= w;
48+
} else if (left_key < right_key) {
49+
pressures[i] -= 1;
50+
pressures[j] += 1;
51+
}
52+
}
53+
}
54+
}
55+
3356
pub fn proposalsFromPressure(pressures: []const i32, cfg: Config, proposals: []i8) void {
3457
std.debug.assert(proposals.len >= pressures.len);
3558

src/core/transport.zig

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
const std = @import("std");
22
const Config = @import("config.zig").Config;
33
const energy = @import("energy.zig");
4+
const key = @import("key.zig");
45
const pressure = @import("pressure.zig");
56
const Stats = @import("stats.zig").Stats;
7+
const util = @import("../internal/util.zig");
68

79
pub const BlockResult = struct {
810
accepted: bool,
@@ -58,8 +60,16 @@ pub fn tryTransportBlock(comptime T: type, block: []T, cfg: Config, stats: ?*Sta
5860
std.debug.assert(block.len <= Config.max_block_size);
5961
if (stats) |s| s.transport_blocks_visited += 1;
6062

61-
const before_energy = energy.blockEnergy(T, block, cfg);
62-
if (block.len <= 1 or before_energy == 0) {
63+
if (block.len <= 1 or util.isSorted(T, block)) {
64+
if (stats) |s| s.transport_blocks_rejected += 1;
65+
return .{ .accepted = false, .before_energy = 0, .after_energy = 0 };
66+
}
67+
68+
var keys: [Config.max_block_size]key.KeyType(T) = undefined;
69+
for (block, 0..) |value, i| keys[i] = key.biasedKey(T, value);
70+
71+
const before_energy = energy.blockEnergyFromKeys(T, keys[0..block.len], cfg);
72+
if (before_energy == 0) {
6373
if (stats) |s| s.transport_blocks_rejected += 1;
6474
return .{ .accepted = false, .before_energy = before_energy, .after_energy = before_energy };
6575
}
@@ -72,8 +82,9 @@ pub fn tryTransportBlock(comptime T: type, block: []T, cfg: Config, stats: ?*Sta
7282
var desired: [Config.max_block_size]usize = undefined;
7383
var source_to_final: [Config.max_block_size]usize = undefined;
7484
var candidate: [Config.max_block_size]T = undefined;
85+
var candidate_keys: [Config.max_block_size]key.KeyType(T) = undefined;
7586

76-
pressure.compute(T, block, cfg, pressures[0..block.len]);
87+
pressure.computeFromKeys(T, keys[0..block.len], cfg, pressures[0..block.len]);
7788
pressure.proposalsFromPressure(pressures[0..block.len], cfg, proposals[0..block.len]);
7889

7990
var changed = false;
@@ -95,9 +106,10 @@ pub fn tryTransportBlock(comptime T: type, block: []T, cfg: Config, stats: ?*Sta
95106
std.debug.assert(isPermutation(source_to_final[0..block.len]));
96107
for (block, 0..) |value, source_index| {
97108
candidate[source_to_final[source_index]] = value;
109+
candidate_keys[source_to_final[source_index]] = keys[source_index];
98110
}
99111

100-
const after_energy = energy.blockEnergy(T, candidate[0..block.len], cfg);
112+
const after_energy = energy.blockEnergyFromKeys(T, candidate_keys[0..block.len], cfg);
101113
if (after_energy >= before_energy) {
102114
std.debug.assert(equalSlices(T, block, original[0..block.len]));
103115
if (stats) |s| s.transport_blocks_rejected += 1;

0 commit comments

Comments
 (0)