Beispiel #1
0
    def __init__(self, task_config, fft_config):
        """Initialize the object with a fixed channel list, a fixed name of the analysis to be performed
        and a fixed set of parameters for the analysis routine.

        Inputs:
        =======
        channel_range: list of strings, defines the name of the channels. This should probably match the
                      name of the channels in the BP file.
        task_config: dict, defines parameters of the analysis to be performed
        fft_config dict, gives parameters of the fourier-transformed data
        """

        # Stores the description of the task. This can be arbitrary
        self.description = task_config["description"]
        # Stores the name of the analysis we are going to execute
        self.analysis = task_config["analysis"]

        # Parse the reference and cross channels.
        try:
            kwargs = task_config["kwargs"]
            # These channels serve as reference for the spectral diagnostics
            self.ref_channels = channel_range.from_str(
                kwargs["ref_channels"][0])
            # These channels serve as the cross-data for the spectrail diagnostics
            self.x_channels = channel_range.from_str(kwargs["x_channels"][0])
        except KeyError:
            self.kwargs = None

        self.fft_config = fft_config

        self.storage_scheme = {
            "ref_channels": self.ref_channels.to_str(),
            "cross_channels": self.x_channels.to_str()
        }
Beispiel #2
0
    def __init__(self, cfg: dict):

        print(
            "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
        )
        print(
            "+                                                                                    +"
        )
        print(
            "+      readers.py is deprecated. Use reader_mpi.py or reader_nompi.py                +"
        )
        print(
            "+                                                                                    +"
        )
        print(
            "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
        )
        comm = MPI.COMM_WORLD
        self.rank = comm.Get_rank()
        self.size = comm.Get_size()

        self.logger = logging.getLogger("simple")

        self.shotnr = cfg["shotnr"]
        self.adios = adios2.ADIOS(MPI.COMM_WORLD)
        self.IO = self.adios.DeclareIO(gen_io_name(self.shotnr))
        self.reader = None

        # Generate a descriptive channel name
        chrg = channel_range.from_str(
            cfg["transport"]["channel_range"][self.rank])
        self.channel_name = gen_channel_name_v2(self.shotnr, chrg.to_str())
        self.logger.info(f"reader_base: channel_name =  {self.channel_name}")
Beispiel #3
0
    def __init__(self, cfg: dict, shotnr: int = 18431):
        """Generates a reader for KSTAR ECEI data.

        Parameters:
        -----------
        cfg: delta config dictionary
        """

        self.adios = adios2.ADIOS()
        self.logger = logging.getLogger("simple")

        self.shotnr = shotnr
        self.IO = self.adios.DeclareIO(gen_io_name(self.shotnr))

        self.reader = None
        # Generate a descriptive channel name
        if len(cfg["channel_range"]) > 1:
            self.logger.error(
                "reader_base is not using MPI. The following channel_ranges are ignored:"
            )
            for crg in cfg["channel_range"][1:]:
                self.logger.error(f"Ignoring channel range {crg}")

        self.chrg = channel_range.from_str(cfg["channel_range"][0])
        self.channel_name = gen_channel_name_v3(cfg["datapath"], self.shotnr,
                                                self.chrg.to_str())
        self.logger.info(f"reader_base: channel_name =  {self.channel_name}")
Beispiel #4
0
    def __init__(self, task_config, fft_config, ecei_config):
        """Initialize the object with a fixed channel list, a fixed name of the analysis to be performed
        and a fixed set of parameters for the analysis routine.

        Inputs:
        =======
        channel_range: list of strings, defines the name of the channels. This should probably match the
                      name of the channels in the BP file.
        task_config: dict, defines parameters of the analysis to be performed
        fft_config dict, gives parameters of the fourier-transformed data
        """

        # Stores the description of the task. This can be arbitrary
        self.description = task_config["description"]
        # Stores the name of the analysis we are going to execute
        self.analysis = task_config["analysis"]

        # Parse the reference and cross channels.
        self.ref_channels = channel_range.from_str(task_config["ref_channels"])
        # These channels serve as the cross-data for the spectral diagnostics
        self.cmp_channels = channel_range.from_str(task_config["cmp_channels"])

        self.task_config = task_config
        self.fft_config = fft_config
        self.ecei_config = ecei_config

        self.storage_scheme = {
            "ref_channels": self.ref_channels.to_str(),
            "cmp_channels": self.cmp_channels.to_str()
        }

        # Construct a list of unique channels
        # F.ex. we have ref_channels [(1,1), (1,2), (1,3)] and cmp_channels = [(1,1), (1,2)]
        # The unique list of channels is then
        # (1,1) x (1,1), (1,1) x (1,2)
        # (1,2) x (1,2) !!! Omit (1,2) x (1,1)
        # (1,3) x (1,1)
        # (1,3) x (1,2)
        channel_pairs = [
            channel_pair(cr, cx) for cr in self.ref_channels
            for cx in self.cmp_channels
        ]
        # Make a list, so that we don't exhause the iterator after the first call.
        self.unique_channels = list(
            more_itertools.distinct_combinations(channel_pairs, 1))
        self.channel_chunk_size = task_config["channel_chunk_size"]
Beispiel #5
0
    def __init__(self, cfg: dict, shotnr: int=18431):

        self.logger = logging.getLogger("simple")

        self.shotnr = shotnr
        self.adios = adios2.ADIOS()
        self.IO = self.adios.DeclareIO(gen_io_name(0))
        self.writer = None
        # Adios2 variable that is defined in DefineVariable
        self.variable = None
        # The shape used to define self.variable
        self.shape = None

        # Generate a descriptive channel name
        self.chrg = channel_range.from_str(cfg["channel_range"][0])
        self.channel_name = gen_channel_name_v3(cfg["datapath"], self.shotnr, self.chrg.to_str())
        self.logger.info(f"writer_base: channel_name =  {self.channel_name}")
Beispiel #6
0
    def __init__(self, cfg):
        """

        Old: filename: str, ch_range: channel_range, chunk_size:int):
        Inputs:
        =======
        cfg: Delta configuration with loader and ECEI section.

        """

        self.ch_range = channel_range.from_str(
            cfg["source"]["channel_range"][0])
        # Create a list of paths in the HDF5 file, corresponding to the specified channels
        self.filename = cfg["source"]["source_file"]
        self.chunk_size = cfg["source"]["chunk_size"]
        self.ecei_cfg = cfg["ECEI_cfg"]
        self.num_chunks = 500
        self.current_chunk = 0

        self.tnorm = cfg["ECEI_cfg"]["t_norm"]

        self.got_normalization = False
Beispiel #7
0
    def __init__(self, cfg: dict, shotnr: int=18431):
        """Generates a reader for KSTAR ECEI data.

        Parameters:
        -----------
        cfg: delta config dictionary
        """

        comm  = MPI.COMM_SELF
        self.rank = comm.Get_rank()
        self.size = comm.Get_size()
        # This should be MPI.COMM_SELF, not MPI.COMM_WORLD
        self.adios = adios2.ADIOS(MPI.COMM_SELF)
        self.logger = logging.getLogger("simple")

        self.shotnr = shotnr
        self.IO = self.adios.DeclareIO(gen_io_name(self.shotnr))
        # Keeps track of the past chunk sizes. This allows to construct a dummy time base

        self.reader = None
        # Generate a descriptive channel name
        self.chrg = channel_range.from_str(cfg["channel_range"][self.rank])
        self.channel_name = gen_channel_name_v3(cfg["datapath"], self.shotnr, self.chrg.to_str())
        self.logger.info(f"reader_base: channel_name =  {self.channel_name}")
Beispiel #8
0
def main():
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    size = comm.Get_size()

    # Parse command line arguments and read configuration file
    parser = argparse.ArgumentParser(
        description="Receive data and dispatch analysis tasks to a mpi queue")
    parser.add_argument('--config',
                        type=str,
                        help='Lists the configuration file',
                        default='configs/config_null.json')
    parser.add_argument('--benchmark', action="store_true")
    args = parser.parse_args()

    global cfg

    with open(args.config, "r") as df:
        cfg = json.load(df)
        df.close()

    # Load logger configuration from file:
    # http://zetcode.com/python/logging/
    with open("configs/logger.yaml", "r") as f:
        log_cfg = yaml.safe_load(f.read())
    logging.config.dictConfig(log_cfg)
    logger = logging.getLogger('simple')

    # Create a global executor
    #executor = concurrent.futures.ThreadPoolExecutor(max_workers=60)
    executor_fft = MPIPoolExecutor(max_workers=16)
    executor_anl = MPIPoolExecutor(max_workers=16)
    #executor = MPIPoolExecutor(max_workers=120)

    adios2_varname = channel_range.from_str(
        cfg["transport_nersc"]["channel_range"][0])

    cfg["run_id"] = ''.join(
        random.choice(string.ascii_uppercase + string.digits)
        for _ in range(6))
    cfg["run_id"] = "ABC128"
    cfg["storage"]["run_id"] = cfg["run_id"]
    logger.info(f"Starting run {cfg['run_id']}")

    # Instantiate a storage backend and store the run configuration and task configuration
    if cfg['storage']['backend'] == "numpy":
        store_backend = backends.backend_numpy(cfg['storage'])
    elif cfg['storage']['backend'] == "mongo":
        store_backend = backends.backend_mongodb(cfg["storage"])
    elif cfg['storage']['backend'] == "null":
        store_backend = backends.backend_null(cfg['storage'])
    else:
        raise NameError(
            f"Unknown storage backend requested: {cfg['storage']['backend']}")

    store_backend.store_one({"run_id": cfg['run_id'], "run_config": cfg})
    logger.info(f"Stored one")

    # Create ADIOS reader object
    reader = reader_gen(cfg["transport_nersc"])
    task_list = task_list_spectral(executor_anl, executor_fft,
                                   cfg["task_list"], cfg["fft_params"],
                                   cfg["ECEI_cfg"], cfg["storage"])
    #task_list = task_list_spectral(executor, cfg["task_list"], cfg["fft_params"], cfg["ECEI_cfg"], cfg["storage"])

    dq = queue.Queue()
    msg = None  #

    tic_main = timeit.default_timer()
    workers = []
    for _ in range(4):
        worker = threading.Thread(target=consume, args=(dq, task_list))
        worker.start()
        workers.append(worker)

    # reader.Open() is blocking until it opens the data file or receives the
    # data stream. Put this right before entering the main loop
    logger.info(f"{rank} Waiting for generator")
    reader.Open()
    logger.info(f"Starting main loop")

    rx_list = []
    while True:
        stepStatus = reader.BeginStep()
        if stepStatus:
            # Read data
            stream_data = reader.Get(adios2_varname, save=False)
            rx_list.append(reader.CurrentStep())

            # Generate message id and publish
            msg = AdiosMessage(tstep_idx=reader.CurrentStep(),
                               data=stream_data)
            dq.put_nowait(msg)
            logger.info(f"Published tidx {msg.tstep_idx}")
            reader.EndStep()
        else:
            logger.info(f"Exiting: StepStatus={stepStatus}")
            break

        if reader.CurrentStep() > 100:
            break

    dq.join()
    logger.info("Queue joined")

    logger.info("Exiting main loop")
    for thr in workers:
        thr.join()

    logger.info("Workers have joined")

    # Shotdown the executioner
    executor_anl.shutdown(wait=True)
    executor_fft.shutdown(wait=True)
    #executor.shutdown(wait=True)

    toc_main = timeit.default_timer()
    logger.info(
        f"Run {cfg['run_id']} finished in {(toc_main - tic_main):6.4f}s")
    logger.info(f"Processed {len(rx_list)} time_chunks: {rx_list}")
Beispiel #9
0
    cfg = json.load(df)

with open('configs/logger.yaml', 'r') as f:
    log_cfg = yaml.safe_load(f.read())
logging.config.dictConfig(log_cfg)

logger = logging.getLogger("generator")

datapath = cfg["transport_nersc"]["datapath"]
nstep = cfg["transport_nersc"]["nstep"]
shotnr = cfg["shotnr"]

# Enforce 1:1 mapping of channels and tasks
assert (len(cfg["transport_nersc"]["channel_range"]) == size)
# Channels this process is reading
ch_rg = channel_range.from_str(cfg["transport_nersc"]["channel_range"][rank])

# Hard-code the total number of data points
#data_pts = int(5e6)
# Hard-code number of data points per data packet
#data_per_batch = int(1e1)
# Calculate the number of required data batches we send over the channel
#num_batches = data_pts // data_per_batch

# Get a data_loader
logger.info("Loading h5 data into memory")
dl = loader_ecei(cfg)
dl.cache()
batch_gen = dl.batch_generator()

logger.info(
Beispiel #10
0

from analysis.channels import channel, channel_range
ch_start = channel("L", 1, 3)
ch_end = channel("L", 4, 5)

# We often need a rectangular selection. This mode refers to the rectangular configuration
# of the channel views. Basically, we specify a recatngle by giving a lower left corner 
# and an upper right corner
# Then iterate within the rectangular bounds defined by this rectangle.
clist = (ch_start, ch_end, mode="rectangle")
for c in clist:
    print(c)

# Test naive iteration where we just take the outer product of two lists:
crg1 = channel_range.from_str("L0101-0104")
crg2 = channel_range.from_str("L0101-0104")

print("Testing naive iteration...")
res = ["{0:d} x {1:d}".format(c1.idx(), c2.idx()) for c1 in clist1 for c2 in clist2]
print(res)


# Test iteration over groups of channels.
# In the spectral analysis we often want to iterate over a list of unique channel pairs.
# That is, the pair (ch1, ch2) is identical to the pair (ch2, ch1).
# We can do this using combinations_with_replacement from itertools as follows.
#
print("Testing iteration over channel lists...")
crg1 = channel_range.from_str("L0101-0104")
combs = list(itertools.combinations_with_replacement(crg1, 2))
Beispiel #11
0
    def __init__(self, task_config, fft_config, ecei_config, storage_config):
        """Initialize the object with a fixed channel list, a fixed name of the analysis to be performed
        and a fixed set of parameters for the analysis routine.

        Inputs:
        =======
        task_config: dict, defines parameters of the analysis to be performed
        fft_config: dict, gives parameters of the fourier-transformed data
        ecei_config: dict, information on ecei diagnostic
        """

        self.task_config = task_config
        self.ecei_config = ecei_config
        self.storage_config = storage_config
        self.logger = logging.getLogger("simple")


        # Stores the description of the task. This can be arbitrary
        self.description = task_config["task_description"]
        # Stores the name of the analysis we are going to execute
        self.analysis = task_config["analysis"]

        if self.analysis == "cross_phase":
            self.kernel = kernel_crossphase_64_cy
        elif self.analysis == "cross_power":
            self.kernel = kernel_crosspower_64_cy
        elif self.analysis == "cross_correlation":
            self.kernel = kernel_crosscorr
        elif self.analysis == "coherence":
            self.kernel = kernel_coherence_64_cy
        elif self.analysis == "skw":
            self.kernel = kernel_skw
        elif self.analysis == "bicoherence":
            self.kernel = kernel_bicoherence
        elif self.analysis == "null":
            self.kernel = kernel_null
        else:
            raise NameError(f"Unknown analysis task {self.analysis}")
        

        # Parse the reference and cross channels.
        self.ref_channels = channel_range.from_str(task_config["ref_channels"])
        # These channels serve as the cross-data for the spectral diagnostics
        self.cmp_channels = channel_range.from_str(task_config["cmp_channels"])

        # Construct a list of unique channels
        # F.ex. we have ref_channels [(1,1), (1,2), (1,3)] and cmp_channels = [(1,1), (1,2)]
        # The unique list of channels is then
        # (1,1) x (1,1), (1,1) x (1,2)
        # (1,2) x (1,2) !!! Omits (1,2) x (1,1)
        # (1,3) x (1,1)
        # (1,3) x (1,2)
        channel_pairs = [channel_pair(cr, cx) for cr in self.ref_channels for cx in self.cmp_channels]
        # Make a list, so that we don't exhaust the iterator after the first call.
        self.unique_channels = [i[0] for i in more_itertools.distinct_combinations(channel_pairs, 1)]
        # Number of channel pairs per future
        self.channel_chunk_size = task_config["channel_chunk_size"]
        # Total number of chunks, i.e. the number of futures appended to the list per call to calculate
        self.num_chunks = (len(self.unique_channels) + self.channel_chunk_size - 1) // self.channel_chunk_size

        # Get the configuration from task_fft_scipy, but don't store the object.
        fft_config["fsample"] = ecei_config["SampleRate"] * 1e3
        self.my_fft = task_fft_scipy(self.channel_chunk_size, fft_config, normalize=True, detrend=True)
        self.fft_params = self.my_fft.get_fft_params()

        self.storage_backend = None
        if self.storage_config["backend"] == "numpy":
            self.storage_backend = backends.backend_numpy(self.storage_config)
        elif self.storage_config["backend"] == "mongo":
            self.storage_backend = backends.backend_mongodb(self.storage_config)
        elif self.storage_config["backend"] == "null":
            self.storage_backend = backends.backend_null(self.storage_config)
        else:
            raise NameError(f"Unknown storage backend requested: {self.storage_config}")

        self.storage_backend.store_metadata(self.task_config, self.get_dispatch_sequence())
Beispiel #12
0
#with open(args.config, "r") as df:
#    cfg = json.load(df)
cfg = json.loads(config_str)

with open('configs/logger.yaml', 'r') as f:
    log_cfg = yaml.safe_load(f.read())
logging.config.dictConfig(log_cfg)

logger = logging.getLogger("simple")

logger.info(f"{cfg['channel_range']}")

gen_id = 1_000 * rank

my_channel_range = channel_range.from_str(cfg["channel_range"][rank])
logger.info(f"rank: {rank} config: {cfg}")

reader = reader_dataman(cfg)
logger.info("Waiting")
reader.Open()

step = 0

while(True):
    stepStatus = reader.BeginStep()
    logger.info(stepStatus)
    if stepStatus == adios2.StepStatus.OK:
        channel_data = reader.get_data("FloatArray")
        reader.EndStep()
        logger.info(f"rank {rank:d}: Step  {reader.CurrentStep():04d}  data = {channel_data}")
Beispiel #13
0
def main():
    # Parse command line arguments and read configuration file
    parser = argparse.ArgumentParser(
        description="Receive data and dispatch analysis tasks to a mpi queue")
    parser.add_argument('--config',
                        type=str,
                        help='Lists the configuration file',
                        default='configs/config_null.json')
    parser.add_argument('--benchmark', action="store_true")
    args = parser.parse_args()

    global cfg

    with open(args.config, "r") as df:
        cfg = json.load(df)
        df.close()

    # Load logger configuration from file:
    # http://zetcode.com/python/logging/
    with open("configs/logger.yaml", "r") as f:
        log_cfg = yaml.safe_load(f.read())
    logging.config.dictConfig(log_cfg)

    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    size = comm.Get_size()

    # Create a global executor
    #executor = concurrent.futures.ThreadPoolExecutor(max_workers=60)
    #executor = MPIPoolExecutor(max_workers=24)
    adios2_varname = channel_range.from_str(
        cfg["transport"]["channel_range"][0])

    with MPICommExecutor(MPI.COMM_WORLD) as executor:
        if executor is not None:

            logger = logging.getLogger('simple')
            cfg["run_id"] = ''.join(
                random.choice(string.ascii_uppercase + string.digits)
                for _ in range(6))
            cfg["run_id"] = "ABC125"
            cfg["storage"]["run_id"] = cfg["run_id"]
            logger.info(f"Starting run {cfg['run_id']}")

            # Instantiate a storage backend and store the run configuration and task configuration
            if cfg['storage']['backend'] == "numpy":
                store_backend = backends.backend_numpy(cfg['storage'])
            elif cfg['storage']['backend'] == "mongo":
                store_backend = backends.backend_mongodb(cfg)
            elif cfg['storage']['backend'] == "null":
                store_backend = backends.backend_null(cfg['storage'])

            logger.info("Storing one")
            store_backend.store_one({
                "run_id": cfg['run_id'],
                "run_config": cfg
            })
            logger.info("Done storing. Continuing:")

            # Create the FFT task
            cfg["fft_params"]["fsample"] = cfg["ECEI_cfg"]["SampleRate"] * 1e3
            my_fft = task_fft_scipy(10_000,
                                    cfg["fft_params"],
                                    normalize=True,
                                    detrend=True)
            fft_params = my_fft.get_fft_params()

            # Create ADIOS reader object
            reader = reader_gen(cfg["transport"])

            # Create a list of individual spectral tasks
            #task_list = []
            #for task_config in cfg["task_list"]:
            #    #task_list.append(task_spectral(task_config, fft_params, cfg["ECEI_cfg"]))
            #    #task_list.append(task_spectral(task_config, cfg["fft_params"], cfg["ECEI_cfg"], cfg["storage"]))
            #    #store_backend.store_metadata(task_config, task_list[-1].get_dispatch_sequence())

            dq = queue.Queue()
            msg = None

            tic_main = timeit.default_timer()
            workers = []
            for _ in range(16):
                #thr = ConsumeThread(dq, executor, task_list, cfg)
                worker = threading.Thread(target=consume,
                                          args=(dq, executor, my_fft,
                                                task_list))
                worker.start()
                workers.append(worker)
            #    logger.info(f"Started thread {thr}")

            # reader.Open() is blocking until it opens the data file or receives the
            # data stream. Put this right before entering the main loop
            logger.info(f"{rank} Waiting for generator")
            reader.Open()
            last_step = 0
            logger.info(f"Starting main loop")

            rx_list = []
            while True:
                stepStatus = reader.BeginStep()
                logger.info(f"currentStep = {reader.CurrentStep()}")
                if stepStatus:
                    # Read data
                    stream_data = reader.Get(adios2_varname, save=False)
                    rx_list.append(reader.CurrentStep())

                    # Generate message id and publish is
                    msg = AdiosMessage(tstep_idx=reader.CurrentStep(),
                                       data=stream_data)
                    dq.put_nowait(msg)
                    logger.info(f"Published message {msg}")
                    reader.EndStep()
                else:
                    logger.info(f"Exiting: StepStatus={stepStatus}")
                    break

                #Early stopping for debug
                if reader.CurrentStep() > 100:
                    logger.info(
                        f"Exiting: CurrentStep={reader.CurrentStep()}, StepStatus={stepStatus}"
                    )
                    dq.put(AdiosMessage(tstep_idx=None, data=None))
                    break

                last_step = reader.CurrentStep()

            dq.join()
            logger.info("Queue joined")

            logger.info("Exiting main loop")
            for thr in workers:
                thr.join()

            logger.info("Workers have joined")

            # Shotdown the executioner
            executor.shutdown(wait=True)

            toc_main = timeit.default_timer()
            logger.info(
                f"Run {cfg['run_id']} finished in {(toc_main - tic_main):6.4f}s"
            )
            logger.info(f"Processed time_chunks {rx_list}")
Beispiel #14
0
#my_fft = task_fft_scipy(10_000, config_fft["fft_params"], normalize=True, detrend=True)
#fft_data = my_fft.do_fft_local(io_array_tr)

with np.load("/global/homes/r/rkube/repos/delta/test_data/fft_array_s0001.npz"
             ) as df:
    fft_data = df["fft_data"]

fft_data_64 = np.ascontiguousarray(fft_data)
fft_data_32 = np.require(fft_data_64,
                         dtype=np.complex64,
                         requirements=['A', 'C'])

###################################################
# Generate channels to iterate over

ref_chrg = channel_range.from_str("L0101-2408")
cmp_chrg = channel_range.from_str("L0101-2408")
channel_pairs = [channel_pair(cr, cx) for cr in ref_chrg for cx in cmp_chrg]
unique_channels = [
    i[0] for i in more_itertools.distinct_combinations(channel_pairs, 1)
]

#ch_it = [channel_pair(channel("L", i, 1), channel("L", i, 2)) for i in range(1, 25)]
#ch_it = ch_it + [channel_pair(channel("L", i, 1), channel("L", i, 3)) for i in range(1, 25)]
#h_it = ch_it + [channel_pair(channel("L", i, 1), channel("L", i, 4)) for i in range(1, 25)]
#ch_it = ch_it + [channel_pair(channel("L", i, 1), channel("L", i, 4)) for i in range(1, 25)]
#ch_it = ch_it + [channel_pair(channel("L", i, 1), channel("L", i, 5)) for i in range(1, 25)]
#ch_it = ch_it + [channel_pair(channel("L", i, 1), channel("L", i, 6)) for i in range(1, 25)]
#ch_it = ch_it + [channel_pair(channel("L", i, 1), channel("L", i, 7)) for i in range(1, 25)]
#ch_it = ch_it + [channel_pair(channel("L", i, 1), channel("L", i, 8)) for i in range(1, 25)]
Beispiel #15
0
def main():
    """Reads items from a ADIOS2 connection and forwards them."""

    parser = argparse.ArgumentParser(description="Receive data and dispatch analysis tasks to a mpi queue")
    parser.add_argument('--config', type=str, help='Lists the configuration file', default='configs/config-middle.json')
    args = parser.parse_args()

    with open(args.config, "r") as df:
        cfg = json.load(df)
        df.close()
    timeout = 30

    # The middleman uses both a reader and a writer. Each is configured with using their respective section 
    # of the config file. Therefore some keys are duplicated, such as channel_range. Make sure that these
    # items are the same in both sections

    assert(cfg["transport_kstar"]["channel_range"] == cfg["transport_nersc"]["channel_range"])

    with open("configs/logger.yaml", "r") as f:
        log_cfg = yaml.safe_load(f.read())
    logging.config.dictConfig(log_cfg)  
    logger = logging.getLogger('middleman')

    # Create ADIOS reader object
    reader = reader_gen(cfg["transport_kstar"])
    reader.Open()

    dq = queue.Queue()
    msg = None
    worker = threading.Thread(target=forward, args=(dq, cfg, timeout))
    worker.start()

    tic = timeit.default_timer()
    nstep = 0
    rx_list = []
    while True:
        stepStatus = reader.BeginStep()    
        logger.info(f"stepStatus = {stepStatus}, currentStep = {reader.CurrentStep()}")

        if stepStatus:
            if reader.CurrentStep() == 0:
                tic = timeit.default_timer()
            # Read data
            stream_data = reader.Get(channel_range.from_str(cfg["transport_kstar"]["channel_range"][0]), 
                                     save=False)

            rx_list.append(reader.CurrentStep())

            # Generate message id and publish is
            msg = AdiosMessage(tstep_idx=reader.CurrentStep(), data=stream_data)
            dq.put_nowait(msg)
            logger.info(f"Published message {msg}")
            reader.EndStep()
            nstep += 1
        else:
            logger.info(f"Exiting: StepStatus={stepStatus}")
            dq.put_nowait(AdiosMessage(tstep_idx=None, data=None))
            break

        last_step = reader.CurrentStep()

    logger.info("Exiting main loop")
    worker.join()
    logger.info("Workers have joined")
    dq.join()
    logger.info("Queue joined")
    toc = timeit.default_timer()
    deltat = toc - tic

    chunk_size = np.prod(stream_data.shape) * stream_data.itemsize / 1024 / 1024
    logger.info(f"Received {len(rx_list)} time chunks: {rx_list}")
    logger.info("")
    logger.info("Summary:")
    logger.info(f"    chunk shape: {stream_data.shape}")
    logger.info(f"    chunk size (MB): {chunk_size:.03f}")
    logger.info(f"    total nstep: {nstep:d}")
    logger.info(f"    total data (MB): {(chunk_size * nstep):03f}")
    logger.info(f"    time (sec): {(deltat):.03f}")
    logger.info(f"    throughput (MB/sec): {(chunk_size * nstep)/(deltat):.03f}")

    logger.info("Finished")