/* * Copyright (c) 2009 Stanford University, unless otherwise specified. * All rights reserved. * * This software was developed by the Pervasive Parallelism Laboratory of * Stanford University, California, USA. * * Permission to use, copy, modify, and distribute this software in source * or binary form for any purpose with or without fee is hereby granted, * provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of Stanford University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ package edu.stanford.ppl.concurrent; import junit.framework.TestCase; public class EpochTest extends TestCase { public void testImmediateClose() { final boolean[] closed = { false }; final Epoch e = new Epoch() { protected void onClosed(final int dataSum) { closed[0] = true; assertEquals(0, dataSum); } }; e.beginClose(); assertTrue(closed[0]); assertNull(e.attemptArrive()); } public void testSimple() { final boolean[] closed = { false }; final Epoch e = new Epoch() { protected void onClosed(final int dataSum) { closed[0] = true; assertEquals(1, dataSum); } }; final Epoch.Ticket t0 = e.attemptArrive(); assertNotNull(t0); t0.leave(1); assertTrue(!closed[0]); e.beginClose(); assertTrue(closed[0]); assertNull(e.attemptArrive()); } public void testPending() { final boolean[] closed = { false }; final Epoch e = new Epoch() { protected void onClosed(final int dataSum) { closed[0] = true; assertEquals(1, dataSum); } }; final Epoch.Ticket t0 = e.attemptArrive(); assertNotNull(t0); e.beginClose(); assertTrue(!closed[0]); t0.leave(1); assertTrue(closed[0]); assertNull(e.attemptArrive()); } public void testParallelCutoff() { final int numThreads = 32; final int arrivalsPerThread = 1000000; final boolean[] closed = { false }; final Epoch e = new Epoch() { protected void onClosed(final int dataSum) { closed[0] = true; } }; ParUtil.parallel(numThreads, new ParUtil.Block() { public void call(final int index) { for (int i = 0; i < arrivalsPerThread; ++i) { final Epoch.Ticket t = e.attemptArrive(); if (t == null) { //System.out.print("thread " + index + " got to " + i + "\n"); return; } t.leave(1 + index); if (index == numThreads - 1 && i == arrivalsPerThread / 2) { e.beginClose(); } } } }); assertTrue(closed[0]); } public void testParallelPerformance() { final int arrivalsPerThread = 1000000; for (int i = 0; i < 3; ++i) { for (int t = 1; t <= Runtime.getRuntime().availableProcessors(); t *= 2) { runNoClosePerf(t, arrivalsPerThread); } for (int f = 2; f <= 4; f *= 2) { runNoClosePerf(Runtime.getRuntime().availableProcessors() * f, arrivalsPerThread / f); } } } private void runNoClosePerf(final int numThreads, final int arrivalsPerThread) { final boolean[] closed = { false }; final Epoch e = new Epoch() { protected void onClosed(final int dataSum) { closed[0] = true; assertEquals(numThreads * (numThreads + 1L) * arrivalsPerThread / 2, dataSum); } }; final long elapsed = ParUtil.timeParallel(numThreads, new ParUtil.Block() { public void call(final int index) { for (int i = 0; i < arrivalsPerThread; ++i) { final Epoch.Ticket t = e.attemptArrive(); assertNotNull(t); t.leave(1 + index); } } }); assertTrue(!closed[0]); e.beginClose(); assertTrue(closed[0]); assertNull(e.attemptArrive()); final long arrivalsPerSec = numThreads * 1000L * arrivalsPerThread / elapsed; System.out.println("numThreads " + numThreads + " arrivalsPerThread " + arrivalsPerThread + " " + "elapsedMillis " + elapsed + " arrivalsPerSec " + arrivalsPerSec + " " + "spread " + e.computeSpread()); } }