def runWorker(comm, histogramSize, gatherInterval, numEventsScaleFactor):
    """worker shared memory example for reducing a histogram to a viewer
   
    Maintains a histogram. Continues to update the communicator and reduce until
    no more workers participate in the communicator.

    Assumes Each reduce is a histogram over only the previous worker events since 
    the last reduce.

    ARGS:
      comm - initial communicator to use
      histogramSize - size of historgram to reduce
      finalReducedHistFilename - filename for numpy .npy file for final histogram
    """
    sharedMemDs = MockDataSource(numEventsScaleFactor)
    localHistogram = np.zeros(histogramSize, np.int64)
    idx = None
    for idx, evt in enumerate(sharedMemDs.events()):
        localHistogram[idx % histogramSize] += 1
        if (idx % gatherInterval) == 0:
            comm = collectiveCommUpdate(comm, stayInComm=True)
            workerReduce(comm, localHistogram)
            localHistogram[:] = 0

    # check for last reduce
    if (idx is not None) and (idx % gatherInterval) != 0:
        comm = collectiveCommUpdate(comm, stayInComm=True)
        workerReduce(comm, localHistogram)

    # remove self from collective communication
    dprint("before final comm update to remove self")
    collectiveCommUpdate(comm, stayInComm=False)
    dprint("after final comm update")
def runViewerReduceHistorgram(comm, histogramSize, finalReducedHistFilename):
    """Viewer shared memory example for reducing a histogram from worker ranks.
   
    Maintains a histogram. Continues to update the communicator and reduce until
    no more workers participate in the communicator.

    Assumes Each reduce is a histogram over only the previous worker events since 
    the last reduce.

    ARGS:
      comm - initial communicator to use
      histogramSize - size of historgram to reduce
      finalReducedHistFilename - filename for numpy .npy file for final histogram
    """
    assert comm.Get_rank() == 0
    histogram = np.zeros(histogramSize, np.int64)
    while True:
        comm = collectiveCommUpdate(comm, stayInComm=True)

        # check if only the viewer is left in communicator and exit if so
        if comm.Get_size() == 1:
            break

        localHistogram = np.zeros(histogramSize, np.int64)
        recvHistogram = np.zeros(histogramSize, np.int64)
        dprint("before Reduce")
        comm.Reduce(sendbuf=[localHistogram, MPI.INT64_T], recvbuf=[recvHistogram, MPI.INT64_T], op=MPI.SUM, root=0)
        histogram[:] += recvHistogram[:]
        print "rank=0 After Reduce. reduced histogram: %s" % histogram
    np.save(file(finalReducedHistFilename, "w"), histogram)
    print "rank=0 saved final reduced historgram=%s in file: %s" % (histogram, finalReducedHistFilename)