final class Worker { // not serializable final int me; // my index in the lifeline graph final int prev; // index of the predecessor in the lifeline graph final int next; // index of the successor in the lifeline graph final Random random; final MessageDigest md = UTS.encoder(); final UTS bag = new UTS(64); // pending requests from thieves final ConcurrentLinkedQueue<Integer> thieves = new ConcurrentLinkedQueue<>(); final AtomicBoolean lifeline; // pending lifeline request? int state = -2; // -3: abort, -2: inactive, -1: running, p: stealing from p Worker(int id, int size, int ratio) { me = (group.indexOf(here()) << power) + id; random = new Random(me); prev = (me + (group.size() << power) - 1) % (group.size() << power); next = (me + 1) % (group.size() << power); lifeline = new AtomicBoolean(((next % ratio) != 0) || ((next / ratio) >= size)); } synchronized void abort() { if (state == -3) { throw new DeadPlaceException(here()); } } public void run() throws DigestException { try { System.err.println(me + " starting"); synchronized (this) { abort(); state = -1; } while (bag.size > 0) { while (bag.size > 0) { for (int n = 500; (n > 0) && (bag.size > 0); --n) { bag.expand(md); } abort(); distribute(); } if (resilient) { map.set(me, bag.trim()); } steal(); } synchronized (this) { abort(); state = -2; } distribute(); lifelinesteal(); } finally { System.err.println(me + " stopping"); } } void lifelinesteal() { if (group.size() == 1 && power == 0) { return; } myUncountedAsyncAt(prev, w -> w.lifeline.set(true)); } void steal() { if (group.size() == 1 && power == 0) { return; } final int me = this.me; int p = random.nextInt((group.size() << power) - 1); if (p >= me) { p++; } synchronized (this) { abort(); state = p; } myUncountedAsyncAt(p, w -> w.request(me)); synchronized (this) { while (state >= 0) { try { wait(); } catch (final InterruptedException e) { } } } } void request(int thief) { synchronized (this) { if (state == -3) { return; } if (state == -1) { thieves.add(thief); return; } } myUncountedAsyncAt(thief, w -> w.deal(null)); } void lifelinedeal(UTS b) throws DigestException { bag.merge(b); run(); } synchronized void deal(UTS loot) { if (state == -3) { return; } if (loot != null) { bag.merge(loot); } state = -1; notifyAll(); } synchronized void unblock(Place p) { state = -3; notifyAll(); } void transfer(int thief, UTS loot) { final UTS bag = this.bag.trim(); final int me = this.me; final int wave = ResilientUTS.this.wave; hz.executeTransaction( (TransactionalTaskContext context) -> { final TransactionalMap<Integer, UTS> map = context.getMap("map" + wave); map.set(me, bag); final UTS old = map.getForUpdate(thief); loot.count = old == null ? 0 : old.count; map.set(thief, loot); return null; }); } void distribute() { if (group.size() == 1 && power == 0) { return; } Integer thief; while ((thief = thieves.poll()) != null) { final UTS loot = bag.split(); if (loot != null && resilient) { transfer(thief, loot); } myUncountedAsyncAt(thief, w -> w.deal(loot)); } if (bag.size > 0 && lifeline.get()) { final UTS loot = bag.split(); if (loot != null) { thief = next; if (resilient) { transfer(thief, loot); } lifeline.set(false); myAsyncAt(next, w -> w.lifelinedeal(loot)); } } } }
public static void main(String[] args) { int depth = 13; try { depth = Integer.parseInt(args[0]); } catch (final Exception e) { } int _power = 1; try { _power = Integer.parseInt(args[1]); } catch (final Exception e) { } final int power = _power; if (System.getProperty(Configuration.APGAS_PLACES) == null) { System.setProperty(Configuration.APGAS_PLACES, "2"); } System.setProperty(Configuration.APGAS_THREADS, "" + ((1 << power) + 1)); final boolean resilient = Boolean.getBoolean(Configuration.APGAS_RESILIENT); final int maxPlaces = places().size(); final MessageDigest md = UTS.encoder(); System.out.println("Warmup..."); final UTS tmp = new UTS(64); tmp.seed(md, 19, depth - 2); finish(() -> ResilientUTS.step(explode(tmp), -1, power, resilient)); System.out.println("Starting..."); Long time = -System.nanoTime(); final UTS bag = new UTS(64); bag.seed(md, 19, depth); List<UTS> bags = explode(bag); int wave = 0; while (bags.get(0).size > 0) { final int w = wave++; final List<UTS> b = bags; System.out.println("Wave: " + w); try { bags = finish(() -> ResilientUTS.step(b, w, power, resilient)); } catch (final DeadPlacesException e) { } } time += System.nanoTime(); System.out.println("Finished."); System.out.println( "Depth: " + depth + ", Places: " + maxPlaces + ", Waves: " + wave + ", Performance: " + bags.get(0).count + "/" + UTS.sub("" + time / 1e9, 0, 6) + " = " + UTS.sub("" + (bags.get(0).count / (time / 1e3)), 0, 6) + "M nodes/s"); }