Skip to content

Commit

Permalink
优化并行枚举算法
Browse files Browse the repository at this point in the history
  • Loading branch information
Funny-ppt committed Mar 21, 2024
1 parent 940f74f commit 88f855b
Showing 1 changed file with 37 additions and 18 deletions.
55 changes: 37 additions & 18 deletions InfrastSim/TimeDriven/WebHelper/Enumerate/EnumerateContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
using InfrastSim.TimeDriven.WebHelper.Enumerate;
using System.Collections;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Text.Json;
using System.Threading.Tasks.Dataflow;
using System.Threading.Channels;

namespace InfrastSim.TimeDriven.WebHelper;
internal class EnumerateContext {
Expand All @@ -17,6 +18,10 @@ internal class EnumerateContext {
Efficiency baseline;
ConcurrentDictionary<int, EnumResult> results = new();

#if DEBUG
int[] _lock = new int[Environment.ProcessorCount * 2];
#endif

Efficiency TestSingle(OpEnumData data) {
var op = simu.Value.Assign(data);
var diff = simu.Value.GetEfficiency() - baseline;
Expand All @@ -25,13 +30,22 @@ Efficiency TestSingle(OpEnumData data) {
}
Efficiency TestMany(IEnumerable<OpEnumData> datas) {
try {
#if DEBUG
var v = Interlocked.CompareExchange(ref _lock[Environment.CurrentManagedThreadId], 1, 0);
if (v != 0) {
if (!Debugger.IsAttached)
Debugger.Launch();
Debugger.Break();
}
#endif
foreach (var data in datas) {
simu.Value.Assign(data);
}
var diff = simu.Value.GetEfficiency() - baseline;
return diff;
} finally {
simu.Value.FillTestOp();
_lock[Environment.CurrentManagedThreadId] = 0;

Check failure on line 48 in InfrastSim/TimeDriven/WebHelper/Enumerate/EnumerateContext.cs

View workflow job for this annotation

GitHub Actions / build-linux-and-wasm

The name '_lock' does not exist in the current context
}
}
bool ValidateResult(in EnumResult result) {
Expand Down Expand Up @@ -90,19 +104,24 @@ public IOrderedEnumerable<EnumResult> EnumerateImpl(JsonDocument json) {
max_size = Math.Min(max_size, max_size_elem.GetInt32());
}

// dataflows
var generateFrames = new TransformManyBlock<OpEnumData, Frame>(GenerateFrames);
var processFrame = new TransformManyBlock<Frame, Frame>(ProcessFrame);

var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
generateFrames.LinkTo(processFrame, linkOptions);
processFrame.LinkTo(processFrame, linkOptions);

var channel = Channel.CreateUnbounded<Frame>();
foreach (var op in ops) {
generateFrames.Post(op);
Task.Run(async () => {
foreach (var frame in GenerateFrames(op))
await channel.Writer.WriteAsync(frame);
});
}
var tasks = new Task[Environment.ProcessorCount];
for (int i = 0; i < tasks.Length; i++) {
tasks[i] = Task.Run(async () => {
while (channel.Reader.TryRead(out var frame)) {
foreach (var outFrame in ProcessFrame(frame)) {
await channel.Writer.WriteAsync(outFrame);
}
}
});
}
generateFrames.Complete();
processFrame.Completion.Wait();
Task.WaitAll(tasks);

return results.Values.Where(v => ValidateResult(v)).OrderByDescending(v => v.eff.GetScore());
}
Expand All @@ -129,7 +148,7 @@ struct Frame {
public int init_size;
public Efficiency base_eff;

public Frame(OpEnumData[] comb, in Efficiency base_eff, int ucnt) {
public Frame(OpEnumData[] comb, Efficiency base_eff, int ucnt) {
this.comb = comb;
this.base_eff = base_eff;
this.gid = GetGroupId(comb);
Expand All @@ -139,7 +158,7 @@ public Frame(OpEnumData[] comb, in Efficiency base_eff, int ucnt) {
uset[op.uid] = true;
}
}
public Frame FromComb(OpEnumData[] new_comb) {
public Frame FromComb(OpEnumData[] new_comb, Efficiency base_eff) {
var op = new_comb[^1];
BitArray new_uset = new(uset);
new_uset[op.uid] = true;
Expand Down Expand Up @@ -191,23 +210,23 @@ IEnumerable<Frame> ProcessFrame(Frame frame) {
}
Efficiency eff;
try { // 检验组合是否能被基建容纳,如果可以,则计算其效率
eff = TestMany(frame.comb);
eff = TestMany(next_comb);
} catch {
continue;
}

// 检验新加入组合的干员是否贡献了额外效率
var extra_eff = eff - frame.base_eff - frame.comb.Last().SingleEfficiency;
var extra_eff = eff - frame.base_eff - op.SingleEfficiency;
if (!extra_eff.IsPositive()) {
continue;
}
// 计算相较于单干员效率总和的额外效率
var tot_extra_eff = eff;
foreach (var opd in frame.comb) {
foreach (var opd in next_comb) {
tot_extra_eff -= opd.SingleEfficiency;
}
results[gid] = new(next_comb, frame.init_size, eff, tot_extra_eff);
if (next_comb.Length < max_size) yield return frame.FromComb(next_comb);
if (next_comb.Length < max_size) yield return frame.FromComb(next_comb, eff);
}
}
}

0 comments on commit 88f855b

Please sign in to comment.