wave9 complete: 458/207 — airflow/argo/pytorch-0003/tf/jax/pyg/grpc/thrift + graphhopper/valhalla
This commit is contained in:
parent
81bc62b9cb
commit
ab10b2f555
22 changed files with 2889 additions and 16 deletions
156
defects/pytorch/unit/PyTorchTracerAlgorithm.java
Normal file
156
defects/pytorch/unit/PyTorchTracerAlgorithm.java
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Unit test for pytorch-0003:
|
||||
* python_function.cpp tracer — std::find on trace_outputs (list) inside node+output loop.
|
||||
* O(N × K × T) → O(T + N × K) with HashSet pre-built before the loop.
|
||||
*
|
||||
* Compile: javac -d . PyTorchTracerAlgorithm.java
|
||||
* Run: java -ea unit.PyTorchTracerAlgorithm
|
||||
*/
|
||||
public class PyTorchTracerAlgorithm {
|
||||
|
||||
static void check(String desc, boolean cond) {
|
||||
if (!cond) throw new AssertionError("FAIL: " + desc);
|
||||
System.out.println("PASS: " + desc);
|
||||
}
|
||||
|
||||
static class Value {
|
||||
final int id;
|
||||
Value(int id) { this.id = id; }
|
||||
}
|
||||
|
||||
static class Node {
|
||||
final List<Value> outputs;
|
||||
Node(List<Value> outputs) { this.outputs = outputs; }
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// SLOW: std::find on traceOutputs list per output per node
|
||||
// -----------------------------------------------------------------------
|
||||
static int slowBuildSubgraph(List<Node> blockNodes, List<Value> traceOutputs) {
|
||||
int ops = 0;
|
||||
for (Node node : blockNodes) { // O(N) nodes
|
||||
for (Value output : node.outputs) { // O(K) outputs per node
|
||||
// std::find on traceOutputs: O(T) per output
|
||||
for (Value tv : traceOutputs) {
|
||||
ops++;
|
||||
if (tv == output) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// FAST: HashSet built once before loop
|
||||
// -----------------------------------------------------------------------
|
||||
static int fastBuildSubgraph(List<Node> blockNodes, List<Value> traceOutputs) {
|
||||
int ops = 0;
|
||||
// Build set once: O(T)
|
||||
Set<Value> traceSet = new HashSet<>();
|
||||
for (Value tv : traceOutputs) {
|
||||
traceSet.add(tv);
|
||||
ops++;
|
||||
}
|
||||
for (Node node : blockNodes) { // O(N) nodes
|
||||
for (Value output : node.outputs) { // O(K) outputs per node
|
||||
ops++; // O(1) set lookup
|
||||
traceSet.contains(output);
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Correctness: both should register the same outputs
|
||||
// -----------------------------------------------------------------------
|
||||
static List<Value> slowRegistered(List<Node> blockNodes, List<Value> traceOutputs) {
|
||||
List<Value> registered = new ArrayList<>();
|
||||
for (Node node : blockNodes) {
|
||||
for (Value output : node.outputs) {
|
||||
if (traceOutputs.contains(output)) registered.add(output);
|
||||
}
|
||||
}
|
||||
return registered;
|
||||
}
|
||||
|
||||
static List<Value> fastRegistered(List<Node> blockNodes, List<Value> traceOutputs) {
|
||||
Set<Value> traceSet = new HashSet<>(traceOutputs);
|
||||
List<Value> registered = new ArrayList<>();
|
||||
for (Node node : blockNodes) {
|
||||
for (Value output : node.outputs) {
|
||||
if (traceSet.contains(output)) registered.add(output);
|
||||
}
|
||||
}
|
||||
return registered;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== PyTorchTracerAlgorithm ===");
|
||||
|
||||
// Worst case: none of block node outputs are in traceOutputs → full scan every time
|
||||
for (int N : new int[]{50, 100, 200, 500}) {
|
||||
int nodesCount = N;
|
||||
int K = 4; // outputs per node
|
||||
int T = N; // trace outputs (different from node outputs)
|
||||
|
||||
// node outputs: values 0..N*K-1
|
||||
List<Value> allNodeVals = new ArrayList<>();
|
||||
for (int i = 0; i < nodesCount * K; i++) allNodeVals.add(new Value(i));
|
||||
|
||||
List<Node> blockNodes = new ArrayList<>();
|
||||
for (int n = 0; n < nodesCount; n++) {
|
||||
blockNodes.add(new Node(allNodeVals.subList(n * K, n * K + K)));
|
||||
}
|
||||
|
||||
// traceOutputs: fresh values NOT in any node output → full miss on every find
|
||||
List<Value> traceOutputs = new ArrayList<>();
|
||||
for (int i = 0; i < T; i++) traceOutputs.add(new Value(nodesCount * K + i));
|
||||
|
||||
int slowOps = slowBuildSubgraph(blockNodes, traceOutputs);
|
||||
int fastOps = fastBuildSubgraph(blockNodes, traceOutputs);
|
||||
|
||||
// Slow: N*K outputs × T full miss = N*K*T
|
||||
int expectedSlowMin = nodesCount * K * T - 1;
|
||||
// Fast: T + N*K lookups
|
||||
int expectedFastMax = T + nodesCount * K + 1;
|
||||
double ratio = (double) slowOps / fastOps;
|
||||
|
||||
check(String.format("pytorch-0003 N=%d: slow ops >= N*K*T=%d (got %d)", N, nodesCount * K * T, slowOps),
|
||||
slowOps >= expectedSlowMin);
|
||||
check(String.format("pytorch-0003 N=%d: fast ops <= T+N*K=%d (got %d)", N, T + nodesCount * K, fastOps),
|
||||
fastOps <= expectedFastMax);
|
||||
check(String.format("pytorch-0003 N=%d: ratio >= 10x (got %.1fx)", N, ratio),
|
||||
ratio >= 10.0);
|
||||
}
|
||||
|
||||
// Correctness: some outputs are trace outputs, both paths must agree
|
||||
{
|
||||
List<Value> pool = new ArrayList<>();
|
||||
for (int i = 0; i < 20; i++) pool.add(new Value(i));
|
||||
|
||||
// Nodes: 5 nodes, 2 outputs each → outputs v0..v9
|
||||
List<Node> nodes = new ArrayList<>();
|
||||
for (int n = 0; n < 5; n++) {
|
||||
nodes.add(new Node(Arrays.asList(pool.get(n * 2), pool.get(n * 2 + 1))));
|
||||
}
|
||||
// traceOutputs: v1, v3, v5, v7 (odd ones)
|
||||
List<Value> traceOutputs = Arrays.asList(pool.get(1), pool.get(3), pool.get(5), pool.get(7));
|
||||
|
||||
List<Value> slow = slowRegistered(nodes, traceOutputs);
|
||||
List<Value> fast = fastRegistered(nodes, traceOutputs);
|
||||
|
||||
check("pytorch-0003 correctness: same count", slow.size() == fast.size());
|
||||
check("pytorch-0003 correctness: 4 outputs registered", slow.size() == 4);
|
||||
for (int i = 0; i < slow.size(); i++) {
|
||||
check("pytorch-0003 correctness: output " + i + " matches", slow.get(i) == fast.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("18/18 PASS"); // 4*3 + 6 correctness = 18
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue