def write_archive(path, name): archive = _otf2.Archive_Open(path, name, _otf2.FILEMODE_WRITE, 1024 * 1024, 4 * 1024 * 1024, _otf2.SUBSTRATE_POSIX, _otf2.COMPRESSION_NONE) flush_callbacks = _otf2.FlushCallbacks(pre_flush=pre_flush, post_flush=post_flush) _otf2.Archive_SetFlushCallbacks(archive, flush_callbacks, None) _otf2.Archive_SetSerialCollectiveCallbacks(archive) write_events(archive) write_definitions(archive) write_global_definitions(archive) _otf2.Archive_Close(archive)
def __init__(self, archive_path, archive_name="traces", file_mode=FileMode.WRITE, chunk_size_events=1024 * 1024, chunk_size_definitions=4 * 1024 * 1024, file_substrate=FileSubstrate.POSIX, compression=Compression.NONE, pre_flush=_default_pre_flush, post_flush=None, flush_data=None, collective_callbacks=None, collective_data=None, global_comm_context=None, local_comm_context=None, memory_callbacks=None, memory_data=None, timer_resolution=None, definitions=None): self._file_mode = file_mode self._first_timestamp = None self._last_timestamp = None self._event_writers = dict() self._handle = _otf2.Archive_Open(archive_path, archive_name, file_mode, chunk_size_events, chunk_size_definitions, file_substrate, compression) # We MUST keep those flush callbacks, they cannot be GC'ed... self._flush_callbacks = _otf2.FlushCallbacks(pre_flush=pre_flush, post_flush=post_flush) _otf2.Archive_SetFlushCallbacks(self._handle, self._flush_callbacks, flush_data) if collective_callbacks is None: _otf2.Archive_SetSerialCollectiveCallbacks(self._handle) else: _otf2.Archive_SetCollectiveCallbacks(self._handle, collective_callbacks, collective_data, global_comm_context, local_comm_context) if memory_callbacks is not None: _otf2.Archive_SetMemoryCallbacks(self._handle, memory_callbacks, memory_data) _otf2.Archive_OpenDefFiles(self._handle) _otf2.Archive_OpenEvtFiles(self._handle) if definitions is None: definitions = DefinitionRegistry() # Reserve id 0 for empty string definitions.strings.create("") if timer_resolution is None: if definitions.clock_properties is None: definitions.clock_properties = ClockProperties( None, timer_resolution=1) else: if definitions.clock_properties is None: definitions.clock_properties = ClockProperties( None, timer_resolution=timer_resolution) else: definitions.clock_properties.timer_resolution = timer_resolution self._global_definition_registry = definitions
def test(self): archive_path = "otf2_AnchorFile_trace/trace" archive_prefix = "archive" archive_name = archive_prefix + ".otf2" # Information stored in the trace. */ chunk_size_events = 1024 * 1024 chunk_size_defs = 4 * 1024 * 1024 substrate = _otf2.SUBSTRATE_POSIX compression = _otf2.COMPRESSION_NONE num_locations = 123 num_definitions = 456 machine_name = "TestMachine" creator = "TestCreator" description = "TestDescription" # We will write only two properties. The third one will be deleted, # that means it won't be written to anchor file. */ invalid_property_names = [ "", # empty "foo", # no "::" at all "::foo", # empty first component 1 "::foo::bar", # empty first component 2 "foo::::", # empty middle component 1 "::::foo", # empty middle component 2 "foo::", # empty last component 1 "foo::bar::", # empty last component 2 "foo::ba ::baz", # invalid character 1 "foo::bar::ba ", # invalid character 2 # NOTE: None is not an invalid property name but an invalid argument ] string_property_names = [ "NamespaceA::Property1", "NamespaceA::Property2", "NamespaceA::Property3" ] string_property_values = ["Valid", "OK", "true"] bool_property_names = [ "NamespaceB::BoolProperty1", "NamespaceB::BoolProperty2" ] bool_property_values = [True, False] property_name_to_delete = "Whatever::Property" arbitrary_property_value = "Whatever::Value" value_to_delete_property = "" archive = _otf2.Archive_Open(archive_path, archive_prefix, _otf2.FILEMODE_WRITE, chunk_size_events, chunk_size_defs, substrate, compression) flush_callbacks = _otf2.FlushCallbacks(pre_flush=pre_flush, post_flush=post_flush) _otf2.Archive_SetFlushCallbacks(archive, flush_callbacks, None) # Set machine name, creator and description (optional) _otf2.Archive_SetMachineName(archive, machine_name) _otf2.Archive_SetCreator(archive, creator) _otf2.Archive_SetDescription(archive, description) _otf2.Archive_SetSerialCollectiveCallbacks(archive) self.archive_set_numbers(archive, num_locations, num_definitions) for invalid_property_name in invalid_property_names: with self.assertRaises(_otf2.Error) as cm: _otf2.Archive_SetProperty(archive, invalid_property_name, "value", True) self.assertEqual( cm.exception.code, _otf2.ERROR_PROPERTY_NAME_INVALID, 'Incorrect return type for invalid property name: "{}"'.format( invalid_property_name)) _otf2.Archive_SetProperty(archive, property_name_to_delete, value_to_delete_property, False) _otf2.Archive_SetProperty(archive, property_name_to_delete, arbitrary_property_value, False) _otf2.Archive_SetProperty(archive, property_name_to_delete, value_to_delete_property, True) _otf2.Archive_SetProperty(archive, string_property_names[0], arbitrary_property_value, False) _otf2.Archive_SetProperty(archive, string_property_names[1], string_property_values[1], False) _otf2.Archive_SetProperty(archive, string_property_names[0], string_property_values[0], True) _otf2.Archive_SetProperty(archive, property_name_to_delete, arbitrary_property_value, False) _otf2.Archive_SetProperty(archive, string_property_names[2], string_property_values[2], False) _otf2.Archive_SetProperty(archive, property_name_to_delete, value_to_delete_property, True) _otf2.Archive_SetProperty(archive, property_name_to_delete, arbitrary_property_value, False) _otf2.Archive_SetProperty(archive, property_name_to_delete, value_to_delete_property, True) _otf2.Archive_SetBoolProperty(archive, bool_property_names[0], bool_property_values[0], False) _otf2.Archive_SetBoolProperty(archive, bool_property_names[1], bool_property_values[1], False) # Close archive. */ _otf2.Archive_Close(archive) # Open new archive. */ full_path = os.path.join(archive_path, archive_name) reader = _otf2.Reader_Open(full_path) _otf2.Reader_SetSerialCollectiveCallbacks(reader) version_read = _otf2.Reader_GetVersion(reader) version_expected = (_otf2.VERSION_MAJOR, _otf2.VERSION_MINOR, _otf2.VERSION_BUGFIX) self.assertEqual(version_read, version_expected, "Version mismatch") num_locations_read = _otf2.Reader_GetNumberOfLocations(reader) self.assertEqual(num_locations, num_locations_read, "Number of locations does not match") num_definitions_read = _otf2.Reader_GetNumberOfGlobalDefinitions( reader, ) self.assertEqual(num_definitions, num_definitions_read, "Number of definitions does not match") (chunk_size_events_read, chunk_size_defs_read) = _otf2.Reader_GetChunkSize(reader) self.assertEqual(chunk_size_events, chunk_size_events_read, "Event chunk size does not match") self.assertEqual(chunk_size_defs, chunk_size_defs_read, "Definition chunk size does not match") substrate_read = _otf2.Reader_GetFileSubstrate(reader) self.assertEqual(substrate, substrate_read, "File substrate does not match") compression_read = _otf2.Reader_GetCompression(reader) self.assertEqual(compression, compression_read, "Compression does not match") machine_name_read = _otf2.Reader_GetMachineName(reader) self.assertEqual(machine_name, machine_name_read, "Machine name does not match") creator_read = _otf2.Reader_GetCreator(reader) self.assertEqual(creator, creator_read, "Creator does not match") description_read = _otf2.Reader_GetDescription(reader) self.assertEqual(description, description_read, "Description does not match") # Get additional meta-information (a.k.a. properties) */ property_names_read = _otf2.Reader_GetPropertyNames(reader) self.assertEqual(len(property_names_read), len(string_property_names) + len(bool_property_names), "Number of properties does not match") for (property_name_read, property_name_written, property_value_written) \ in zip(property_names_read, string_property_names + bool_property_names, string_property_values + bool_property_values): # First, this test writes #number_of_string_properties properties of type # string to the anchor file. Afterwards, #number_of_bool_properties are # written to the anchor file. # Property names are store in upper case. If everything works correctly, # _otf2.Reader_GetProperty will return our property names converted from # mixed case to upper case. Therefore, we also have to convert property # names to upper case. converted_name = property_name_written.upper() self.assertEqual(property_name_read, converted_name, "Property name does not match") if isinstance(property_value_written, str): property_value_read = _otf2.Reader_GetProperty( reader, property_name_read) elif isinstance(property_value_written, bool): property_value_read = _otf2.Reader_GetBoolProperty( reader, property_name_read) else: self.fail("Invalid written property type") self.assertEqual(property_value_written, property_value_read, "Property value does not match") _otf2.Reader_Close(reader)
def write_trace(self): archive_path = "%s/%s" % (self.tmp_dirname, self.archive_name) archive = _otf2.Archive_Open(archive_path, "trace_files", _otf2.FILEMODE_WRITE, 256 * 1024, _otf2.UNDEFINED_UINT64, _otf2.SUBSTRATE_POSIX, _otf2.COMPRESSION_NONE) flush_callbacks = _otf2.FlushCallbacks(pre_flush=pre_flush, post_flush=post_flush) _otf2.Archive_SetFlushCallbacks(archive, flushCallbacks=flush_callbacks, flushData=None) _otf2.Archive_SetSerialCollectiveCallbacks(archive) _otf2.Archive_SetDescription( archive, description="OTF2 trace for integrity test.") _otf2.Archive_SetCreator(archive, creator="OTF2_Integrity") _otf2.Archive_SetDefChunkSize(archive, 4 * 1024 * 1024) global_def_writer = _otf2.Archive_GetGlobalDefWriter(archive) _otf2.GlobalDefWriter_WriteString(global_def_writer, 0, "Process") for location in self.locations: _otf2.GlobalDefWriter_WriteLocation(global_def_writer, location, 0, _otf2.LOCATION_TYPE_CPU_THREAD, self.num_events * 6, 0) _otf2.GlobalDefWriter_WriteString(global_def_writer, 1, "MPI_Send") _otf2.GlobalDefWriter_WriteString(global_def_writer, 2, "Send an MPI message") _otf2.GlobalDefWriter_WriteString(global_def_writer, 3, "MPI_Recv") _otf2.GlobalDefWriter_WriteString(global_def_writer, 4, "Receive an MPI message") _otf2.GlobalDefWriter_WriteRegion(global_def_writer, 0, 1, 1, 2, _otf2.REGION_ROLE_UNKNOWN, _otf2.PARADIGM_UNKNOWN, _otf2.REGION_FLAG_NONE, 0, 0, 0) _otf2.GlobalDefWriter_WriteRegion(global_def_writer, 1, 3, 3, 4, _otf2.REGION_ROLE_UNKNOWN, _otf2.PARADIGM_UNKNOWN, _otf2.REGION_FLAG_NONE, 0, 0, 0) _otf2.Archive_CloseGlobalDefWriter(archive, global_def_writer) _otf2.Archive_OpenDefFiles(archive) for location in self.locations: def_writer = _otf2.Archive_GetDefWriter(archive, location) _otf2.Archive_CloseDefWriter(archive, def_writer) _otf2.Archive_CloseDefFiles(archive) _otf2.Archive_OpenEvtFiles(archive) for _ in range(self.num_events): for location in self.locations: evt_writer = _otf2.Archive_GetEvtWriter(archive, location) ts = get_time() _otf2.EvtWriter_Enter(evt_writer, None, ts, 0) _otf2.EvtWriter_MpiSend(evt_writer, None, ts, location, 0, 42, 1024) _otf2.EvtWriter_Leave(evt_writer, None, get_time(), 0) _otf2.EvtWriter_Enter(evt_writer, None, get_time(), 1) ts = get_time() _otf2.EvtWriter_MpiRecv(evt_writer, None, ts, location, 0, 42, 1024) _otf2.EvtWriter_Leave(evt_writer, None, ts, 1) for location in self.locations: evt_writer = _otf2.Archive_GetEvtWriter(archive, location) _otf2.Archive_CloseEvtWriter(archive, evt_writer) _otf2.Archive_CloseEvtFiles(archive) _otf2.Archive_Close(archive)
def main(): archive_name = "TestTrace" # Array used to store metric values */ metric_values = (_otf2.MetricValue * NUM_OF_METRICS)() # If you add new metrics please adapt also the array of metric types # and the routine to generate random metric values. */ # Array of metric types */ metric_types = [ _otf2.TYPE_UINT64, _otf2.TYPE_DOUBLE, _otf2.TYPE_INT64, _otf2.TYPE_DOUBLE, _otf2.TYPE_INT64 ] # Initialize accumulated metric */ metric_values[0].unsigned_int = 0 metric_values[1].floating_point = 12.5 metric_values[2].signed_int = 1 metric_values[3].floating_point = 10.0 metric_values[4].unsigned_int = 1 # Distribute metric members to its classes */ metric_members_of_class_1 = [METRIC_A, METRIC_B] metric_members_of_class_2 = [METRIC_C] metric_members_of_class_3 = [METRIC_D] metric_members_of_class_4 = [METRIC_E] # Array of offsets needed to get correct type or values of a metric in corresponding arrays. */ metric_classes_offsets = [0, 2, 3, 4, 4] # The collection of metric classes of instances for which we write metric events */ class MetricWriteParameter: def __init__(self, id_, offset, count, record_for_location): self.id = id_ self.metric_types = metric_types[offset:offset + count] self.metric_values = metric_values[offset:offset + count] self.record_for_location = record_for_location # FIXME missing class 4 metric_write_parameters = [ MetricWriteParameter(METRIC_CLASS_1, metric_classes_offsets[0], len(metric_members_of_class_1), record_for_all_locations), MetricWriteParameter(METRIC_CLASS_2, metric_classes_offsets[1], len(metric_members_of_class_2), record_for_all_locations), MetricWriteParameter(METRIC_CLASS_3, metric_classes_offsets[2], len(metric_members_of_class_3), record_for_all_locations), MetricWriteParameter(METRIC_INSTANCE_1, metric_classes_offsets[3], len(metric_members_of_class_4), record_for_location_0) ] def create_new_metric_values(): metric_values[0].unsigned_int += 1 metric_values[1].floating_point += 12.5 metric_values[2].unsigned_int = -metric_values[2].unsigned_int metric_values[3].floating_point += 10.0 metric_values[4].unsigned_int += 1 def write_metrics(new, metric_time, metric_rank, metric_thread): if new: create_new_metric_values() for metric_write_parameter in metric_write_parameters: if metric_write_parameter.record_for_location( metric_rank, metric_thread): _otf2.EvtWriter_Metric(evt_writer, None, metric_time, metric_write_parameter.id, metric_write_parameter.metric_types, metric_write_parameter.metric_values) # Calculate number of MPI ranks and OpenMP threads. */ num_ranks = 1 num_threads = 1 if otf2_MPI: num_ranks = otf2_LOCATIONS archive_path = "otf2_trace_gen_trace_mpi_{}_{}{}".format( num_ranks, otf2_EVENTS, "_attr" if otf2_ATTRIBUTES else "") elif otf2_OPENMP: num_threads = otf2_LOCATIONS archive_path = "otf2_trace_gen_trace_omp_{}_{}{}".format( num_threads, otf2_EVENTS, "_attr" if otf2_ATTRIBUTES else "") elif otf2_HYBRID: if (otf2_LOCATIONS % 4) == 0: num_threads = 4 elif (otf2_LOCATIONS % 3) == 0: num_threads = 3 elif (otf2_LOCATIONS % 2) == 0: num_threads = 2 else: # FIXME shadow for num_threads in range(5, otf2_LOCATIONS): if (otf2_LOCATIONS % num_threads) == 0: break num_ranks = otf2_LOCATIONS // num_threads archive_path = "otf2_trace_gen_trace_mpi_omp_{}x{}_{}{}".format( num_ranks, num_threads, otf2_EVENTS, "_attr" if otf2_ATTRIBUTES else "") else: raise RuntimeError("No paradigm set") print("\nGenerating an OTF2 test archive") print("with {} rank(s) and {} thread(s) each ({} locations total)".format( num_ranks, num_threads, otf2_LOCATIONS)) print("to {}/{}.otf2\n".format(archive_path, archive_name)) if os.path.isdir(archive_path): for i in itertools.count(): archive_path_backup = "{}_bk_{}".format(archive_path, i) if not os.path.exists(archive_path_backup): os.rename(archive_path, archive_path_backup) break # Create new archive handle. */ archive = _otf2.Archive_Open(archive_path, archive_name, _otf2.FILEMODE_WRITE, 1024 * 1024, 4 * 1024 * 1024, _otf2.SUBSTRATE_POSIX, _otf2.COMPRESSION_NONE) flush_callbacks = _otf2.FlushCallbacks(pre_flush=pre_flush, post_flush=post_flush) _otf2.Archive_SetFlushCallbacks(archive, flush_callbacks, None) # Set description, and creator. */ _otf2.Archive_SetSerialCollectiveCallbacks(archive) _otf2.Archive_SetDescription( archive, "Simple OTF2 trace archive to valid reader components") _otf2.Archive_SetCreator(archive, "otf2_trace_gen") # Generate location IDs. Just to have non-consecutive location IDs. */ locations = [] mpi_ranks = [] master_threads = [] for rank in range(num_ranks): for thread in range(num_threads): locations.append((rank << 16) + thread) mpi_ranks.append(rank) master_threads.append(rank << 16) _otf2.Archive_OpenEvtFiles(archive) # Create local event writer. */ # Create an attribute list. */ attributes = None if otf2_ATTRIBUTES: attributes = _otf2.AttributeList_New() t = get_time() for rank in range(num_ranks): evt_writer = _otf2.Archive_GetEvtWriter(archive, master_threads[rank]) # Enter main. */ write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Enter(evt_writer, attributes, t, REGION_MAIN) for event in range(otf2_EVENTS): t = get_time() # FIXME - this makes no sense if not otf2_OPENMP: for rank in range(num_ranks): evt_writer = _otf2.Archive_GetEvtWriter( archive, master_threads[rank]) # Write enter MPI_Send. */ write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Enter(evt_writer, attributes, t, REGION_MPI_SEND) _otf2.EvtWriter_MpiSend(evt_writer, None, t, (rank + 1) % num_ranks, rank, 0, 1024) t = get_time() # Write leave MPI_Send. */ write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Leave(evt_writer, attributes, t, REGION_MPI_SEND) # Immediately enter the MPI_Recv */ t = get_time() # Write enter MPI_Recv. */ write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Enter(evt_writer, attributes, t, REGION_MPI_RECV) if not otf2_OPENMP: for rank in range(num_ranks): evt_writer = _otf2.Archive_GetEvtWriter( archive, master_threads[rank]) _otf2.EvtWriter_MpiRecv(evt_writer, None, t, (rank + num_ranks - 1) % num_ranks, rank, 0, 1024) # Write enter MPI_Recv. */ write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Leave(evt_writer, attributes, t, REGION_MPI_RECV) # MPI Barrier. */ t = get_time() write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Enter(evt_writer, attributes, t, REGION_MPI_BARRIER) _otf2.EvtWriter_MpiCollectiveBegin(evt_writer, None, t) # End all started MPI_Barrier */ t = get_time() if not otf2_OPENMP: for rank in range(num_ranks): evt_writer = _otf2.Archive_GetEvtWriter( archive, master_threads[rank]) _otf2.EvtWriter_MpiCollectiveEnd(evt_writer, None, t, _otf2.COLLECTIVE_OP_BARRIER, rank, _otf2.UNDEFINED_UINT32, 0, 0) write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Leave(evt_writer, attributes, t, REGION_MPI_BARRIER) # If in OpenMP or Hybrid mode. */ if not otf2_MPI: t_enter = get_time() t_leave = get_time() for rank in range(num_ranks): evt_writer = _otf2.Archive_GetEvtWriter( archive, master_threads[rank]) # At this point the master creates a team of several parallel threads */ _otf2.EvtWriter_OmpFork(evt_writer, attributes, t_enter, num_threads) for rank in range(num_ranks): for thread in range(num_threads): evt_writer = _otf2.Archive_GetEvtWriter( archive, locations[num_threads * rank + thread]) # Enter OpenMP parallel loop (outer region). */ write_metrics(True, t_enter, rank, thread) add_attributes(attributes) _otf2.EvtWriter_Enter(evt_writer, attributes, t_enter, REGION_OPENMP_PARALLEL) # Enter OpenMP parallel loop (inner region). */ write_metrics(False, t_enter, rank, thread) add_attributes(attributes) _otf2.EvtWriter_Enter(evt_writer, attributes, t_enter, REGION_OPENMP_LOOP) # Enter OpenMP implicit barrier. */ write_metrics(False, t_enter, rank, thread) add_attributes(attributes) _otf2.EvtWriter_Enter(evt_writer, attributes, t_enter, REGION_OPENMP_IMPLICIT_BARRIER) for rank in range(num_ranks): for thread in range(num_threads): evt_writer = _otf2.Archive_GetEvtWriter( archive, locations[num_threads * rank + thread]) # Leave OpenMP implicit barrier. */ write_metrics(True, t_leave, rank, thread) add_attributes(attributes) _otf2.EvtWriter_Leave(evt_writer, attributes, t_leave, REGION_OPENMP_IMPLICIT_BARRIER) # Leave OpenMP parallel loop (inner region). */ write_metrics(False, t_leave, rank, thread) add_attributes(attributes) _otf2.EvtWriter_Leave(evt_writer, attributes, t_leave, REGION_OPENMP_LOOP) # Leave OpenMP parallel loop (outer region). */ write_metrics(False, t_leave, rank, thread) add_attributes(attributes) _otf2.EvtWriter_Leave(evt_writer, attributes, t_leave, REGION_OPENMP_PARALLEL) for rank in range(num_ranks): evt_writer = _otf2.Archive_GetEvtWriter( archive, master_threads[rank]) # All threads have finished execution of statements in parallel region. # Now they synchronize and terminates. Only the master continues execution. */ t_leave = get_time() _otf2.EvtWriter_OmpJoin(evt_writer, attributes, t_leave) if not otf2_OPENMP: for rank in range(num_ranks): evt_writer = _otf2.Archive_GetEvtWriter( archive, master_threads[rank]) t = get_time() write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Enter(evt_writer, attributes, t, REGION_MPI_BARRIER) _otf2.EvtWriter_MpiCollectiveBegin(evt_writer, None, t) # End all started MPI_Barrier */ t = get_time() if not otf2_OPENMP: for rank in range(num_ranks): evt_writer = _otf2.Archive_GetEvtWriter( archive, master_threads[rank]) _otf2.EvtWriter_MpiCollectiveEnd(evt_writer, None, t, _otf2.COLLECTIVE_OP_BARRIER, rank, _otf2.UNDEFINED_UINT32, 0, 0) write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Leave(evt_writer, attributes, t, REGION_MPI_BARRIER) t = get_time() for rank in range(num_ranks): evt_writer = _otf2.Archive_GetEvtWriter(archive, master_threads[rank]) # Leave main. */ write_metrics(True, t, rank, 0) add_attributes(attributes) _otf2.EvtWriter_Leave(evt_writer, attributes, t, REGION_MAIN) # last timestamp */ t = get_time() number_of_events_per_location = [] for rank in range(num_ranks): for thread in range(num_threads): evt_writer = _otf2.Archive_GetEvtWriter( archive, locations[num_threads * rank + thread]) n = _otf2.EvtWriter_GetNumberOfEvents(evt_writer) number_of_events_per_location.append(n) _otf2.Archive_CloseEvtWriter(archive, evt_writer) _otf2.Archive_CloseEvtFiles(archive) # Write the global and local definitions. */ glob_def_writer = _otf2.Archive_GetGlobalDefWriter(archive) # Write the timerange of the trace */ _otf2.GlobalDefWriter_WriteClockProperties(glob_def_writer, 1, 0, t) _otf2.GlobalDefWriter_WriteString(glob_def_writer, STRING_EMPTY, "") string = STRING_EMPTY + 1 # Write paradigm definitions */ if otf2_MPI or otf2_HYBRID: _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "MPI") _otf2.GlobalDefWriter_WriteParadigm(glob_def_writer, _otf2.PARADIGM_MPI, string, _otf2.PARADIGM_CLASS_PROCESS) string += 1 _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "MPI_COMM_${id}") value = _otf2.AttributeValue() value.stringRef = string string += 1 _otf2.GlobalDefWriter_WriteParadigmProperty( glob_def_writer, _otf2.PARADIGM_MPI, _otf2.PARADIGM_PROPERTY_COMM_NAME_TEMPLATE, _otf2.TYPE_STRING, value) _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "MPI_WIN_${id}") value.stringRef = string string += 1 _otf2.GlobalDefWriter_WriteParadigmProperty( glob_def_writer, _otf2.PARADIGM_MPI, _otf2.PARADIGM_PROPERTY_RMA_WIN_NAME_TEMPLATE, _otf2.TYPE_STRING, value) (type_, value) = _otf2.AttributeValue_SetBoolean(_otf2.FALSE) _otf2.GlobalDefWriter_WriteParadigmProperty( glob_def_writer, _otf2.PARADIGM_OPENMP, _otf2.PARADIGM_PROPERTY_RMA_ONLY, type_, value) if otf2_OPENMP or otf2_HYBRID: _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "OpenMP") _otf2.GlobalDefWriter_WriteParadigm( glob_def_writer, _otf2.PARADIGM_OPENMP, string, _otf2.PARADIGM_CLASS_THREAD_FORK_JOIN) string += 1 _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "OMP Thread Team ${id}") value = _otf2.AttributeValue() value.stringRef = string string += 1 # FIXME seems like a bad idea to write a hardcoded number 4 here _otf2.GlobalDefWriter_WriteParadigmProperty(glob_def_writer, _otf2.PARADIGM_OPENMP, 4, _otf2.TYPE_STRING, value) # Write system tree definitions. */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "Rack 0") _otf2.GlobalDefWriter_WriteString(glob_def_writer, string + 1, "Rack") _otf2.GlobalDefWriter_WriteSystemTreeNode(glob_def_writer, 0, string, string + 1, _otf2.UNDEFINED_SYSTEM_TREE_NODE) string += 2 _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "Blade") string_blade = string string += 1 for rank in range(num_ranks // 2): name_buffer = "Blade #{}".format(rank) _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, name_buffer) _otf2.GlobalDefWriter_WriteSystemTreeNode(glob_def_writer, rank + 1, string, string_blade, 0) string += 1 # Write location group and location definitions. */ for rank in range(num_ranks): name_buffer = "Process {}".format(rank) _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, name_buffer) _otf2.GlobalDefWriter_WriteLocationGroup( glob_def_writer, rank, string, _otf2.LOCATION_GROUP_TYPE_PROCESS, (rank // 2) + 1) string += 1 for thread in range(num_threads): name_buffer = "Thread {}.{}".format(rank, thread) _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, name_buffer) _otf2.GlobalDefWriter_WriteLocation( glob_def_writer, locations[rank * num_threads + thread], string, _otf2.LOCATION_TYPE_CPU_THREAD, number_of_events_per_location[rank * num_threads + thread], rank) string += 1 # Write region definition for "main". */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "main (mangled name)") string += 1 _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "main (demangled name)") _otf2.GlobalDefWriter_WriteRegion(glob_def_writer, REGION_MAIN, string, string - 1, STRING_EMPTY, _otf2.REGION_ROLE_UNKNOWN, _otf2.PARADIGM_UNKNOWN, _otf2.REGION_FLAG_NONE, STRING_EMPTY, 0, 0) string += 1 # Write region definition for an all-threads function. */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "!$omp parallelfor") _otf2.GlobalDefWriter_WriteRegion(glob_def_writer, REGION_OPENMP_PARALLEL, string, string, STRING_EMPTY, _otf2.REGION_ROLE_UNKNOWN, _otf2.PARADIGM_UNKNOWN, _otf2.REGION_FLAG_NONE, STRING_EMPTY, 0, 0) _otf2.GlobalDefWriter_WriteRegion(glob_def_writer, REGION_OPENMP_LOOP, string, string, STRING_EMPTY, _otf2.REGION_ROLE_UNKNOWN, _otf2.PARADIGM_UNKNOWN, _otf2.REGION_FLAG_NONE, STRING_EMPTY, 0, 0) string += 1 # Write region definition for OpenMP implicit barrier. */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "!$omp implicit barrier") _otf2.GlobalDefWriter_WriteRegion( glob_def_writer, REGION_OPENMP_IMPLICIT_BARRIER, string, string, STRING_EMPTY, _otf2.REGION_ROLE_UNKNOWN, _otf2.PARADIGM_UNKNOWN, _otf2.REGION_FLAG_NONE, STRING_EMPTY, 0, 0) string += 1 # Write region definition for "MPI_Send". */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "MPI_Send") _otf2.GlobalDefWriter_WriteRegion(glob_def_writer, REGION_MPI_SEND, string, string, STRING_EMPTY, _otf2.REGION_ROLE_UNKNOWN, _otf2.PARADIGM_UNKNOWN, _otf2.REGION_FLAG_NONE, STRING_EMPTY, 0, 0) string += 1 # Write region definition for "MPI_Recv". */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "MPI_Recv") _otf2.GlobalDefWriter_WriteRegion(glob_def_writer, REGION_MPI_RECV, string, string, STRING_EMPTY, _otf2.REGION_ROLE_UNKNOWN, _otf2.PARADIGM_UNKNOWN, _otf2.REGION_FLAG_NONE, STRING_EMPTY, 0, 0) string += 1 # Write region definition for "MPI_Barrier". */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "MPI_Barrier") _otf2.GlobalDefWriter_WriteRegion(glob_def_writer, REGION_MPI_BARRIER, string, string, STRING_EMPTY, _otf2.REGION_ROLE_UNKNOWN, _otf2.PARADIGM_UNKNOWN, _otf2.REGION_FLAG_NONE, STRING_EMPTY, 0, 0) string += 1 # Define the list of locations which are mpi ranks */ _otf2.GlobalDefWriter_WriteGroup(glob_def_writer, GROUP_MPI_LOCATIONS, STRING_EMPTY, _otf2.GROUP_TYPE_COMM_LOCATIONS, _otf2.PARADIGM_MPI, _otf2.GROUP_FLAG_NONE, master_threads) # Define the MPI group for MPI_COMM_WORLD */ _otf2.GlobalDefWriter_WriteGroup(glob_def_writer, GROUP_MPI_COMM_WORLD, STRING_EMPTY, _otf2.GROUP_TYPE_COMM_GROUP, _otf2.PARADIGM_MPI, _otf2.GROUP_FLAG_NONE, mpi_ranks) # Define the MPI group for COMM_SELF like communicators */ _otf2.GlobalDefWriter_WriteGroup(glob_def_writer, GROUP_MPI_COMM_SELF, STRING_EMPTY, _otf2.GROUP_TYPE_COMM_SELF, _otf2.PARADIGM_MPI, _otf2.GROUP_FLAG_NONE, []) # Define a group that includes all locations. It will be used by metric instance. */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "All locations") _otf2.GlobalDefWriter_WriteGroup(glob_def_writer, GROUP_ALL_LOCATIONS, string, _otf2.GROUP_TYPE_LOCATIONS, _otf2.PARADIGM_UNKNOWN, _otf2.GROUP_FLAG_NONE, locations) string += 1 # Define MPI_COMM_WORD */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "My MPI_COMM_WORLD communicator") _otf2.GlobalDefWriter_WriteComm(glob_def_writer, MPI_COMM_MPI_COMM_WORLD, string, GROUP_MPI_COMM_WORLD, _otf2.UNDEFINED_COMM) string += 1 # Define MPI_COMM_SELF */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "My MPI_COMM_SELF communicator") _otf2.GlobalDefWriter_WriteComm(glob_def_writer, MPI_COMM_MPI_COMM_SELF, string, GROUP_MPI_COMM_SELF, _otf2.UNDEFINED_COMM) string += 1 # Write member definition of first metric */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "Metric_A") string += 1 _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "FLOPS") _otf2.GlobalDefWriter_WriteMetricMember(glob_def_writer, METRIC_A, string - 1, STRING_EMPTY, _otf2.METRIC_TYPE_PAPI, _otf2.METRIC_ACCUMULATED_START, metric_types[0], _otf2.BASE_DECIMAL, 0, string) string += 1 # Write member definition of second metric */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "Metric_B") string += 1 _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "s") _otf2.GlobalDefWriter_WriteMetricMember(glob_def_writer, METRIC_B, string - 1, STRING_EMPTY, _otf2.METRIC_TYPE_OTHER, _otf2.METRIC_ABSOLUTE_POINT, metric_types[1], _otf2.BASE_DECIMAL, -6, string) string += 1 # Write member definition of third metric */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "Metric_C") string += 1 _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "apples") _otf2.GlobalDefWriter_WriteMetricMember(glob_def_writer, METRIC_C, string - 1, STRING_EMPTY, _otf2.METRIC_TYPE_OTHER, _otf2.METRIC_RELATIVE_LAST, metric_types[2], _otf2.BASE_DECIMAL, 0, string) string += 1 # Write member definition of fourth metric */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "Metric_D") string += 1 _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "pears") _otf2.GlobalDefWriter_WriteMetricMember(glob_def_writer, METRIC_D, string - 1, STRING_EMPTY, _otf2.METRIC_TYPE_OTHER, _otf2.METRIC_ABSOLUTE_POINT, metric_types[3], _otf2.BASE_DECIMAL, 0, string) string += 1 # Write member definition of fifth metric */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "Metric_E") string += 1 _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "cherries") _otf2.GlobalDefWriter_WriteMetricMember(glob_def_writer, METRIC_E, string - 1, STRING_EMPTY, _otf2.METRIC_TYPE_OTHER, _otf2.METRIC_ABSOLUTE_POINT, metric_types[4], _otf2.BASE_DECIMAL, 0, string) string += 1 # Define metric classes and instances */ _otf2.GlobalDefWriter_WriteMetricClass(glob_def_writer, METRIC_CLASS_1, metric_members_of_class_1, _otf2.METRIC_SYNCHRONOUS_STRICT, _otf2.RECORDER_KIND_CPU) _otf2.GlobalDefWriter_WriteMetricClass(glob_def_writer, METRIC_CLASS_2, metric_members_of_class_2, _otf2.METRIC_SYNCHRONOUS_STRICT, _otf2.RECORDER_KIND_CPU) _otf2.GlobalDefWriter_WriteMetricClass(glob_def_writer, METRIC_CLASS_3, metric_members_of_class_3, _otf2.METRIC_SYNCHRONOUS_STRICT, _otf2.RECORDER_KIND_CPU) _otf2.GlobalDefWriter_WriteMetricClass(glob_def_writer, METRIC_CLASS_4, metric_members_of_class_4, _otf2.METRIC_ASYNCHRONOUS, _otf2.RECORDER_KIND_ABSTRACT) # We can define an instance with differing recorder and scope. # In this example metric values are valid for all locationa # but are recorded on first location. */ _otf2.GlobalDefWriter_WriteMetricInstance(glob_def_writer, METRIC_INSTANCE_1, METRIC_CLASS_4, locations[0], _otf2.SCOPE_GROUP, GROUP_ALL_LOCATIONS) # write attribute defs */ if otf2_ATTRIBUTES: for a, attribute_def in enumerate(attribute_defs): _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, attribute_def.name) _otf2.GlobalDefWriter_WriteAttribute(glob_def_writer, a, string, STRING_EMPTY, attribute_def.type) string += 1 # create a sub communicator of MPI_COMM_WORLD and embed an hyper cube. */ num_cube_ranks = gpot(num_ranks) cube_ranks = list(range(num_cube_ranks)) # Define the MPI group for the hyper cube */ _otf2.GlobalDefWriter_WriteGroup(glob_def_writer, GROUP_MPI_COMM_CUBE, STRING_EMPTY, _otf2.GROUP_TYPE_COMM_GROUP, _otf2.PARADIGM_MPI, _otf2.GROUP_FLAG_NONE, cube_ranks) # Define MPI_COMM_MPI_COMM_CUBE */ _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "MPI_COMM_CUBE") _otf2.GlobalDefWriter_WriteComm(glob_def_writer, MPI_COMM_MPI_COMM_CUBE, string, GROUP_MPI_COMM_WORLD, MPI_COMM_MPI_COMM_WORLD) string += 1 num_cube_dims = 0 cube_dim = 1 while cube_dim < num_cube_ranks: name = "Cube {}".format(cube_dim) _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, name) _otf2.GlobalDefWriter_WriteCartDimension(glob_def_writer, num_cube_dims, string, 2, _otf2.CART_PERIODIC_FALSE) string += 1 num_cube_dims += 1 cube_dim <<= 1 cube_dimensions = [ _otf2.CartDimensionRef(cube_dim) for cube_dim in range(num_cube_dims) ] _otf2.GlobalDefWriter_WriteString(glob_def_writer, string, "Hyper Cube") _otf2.GlobalDefWriter_WriteCartTopology(glob_def_writer, 0, string, MPI_COMM_MPI_COMM_CUBE, cube_dimensions) string += 1 for rank in range(num_cube_ranks): cube_coordinates = [ 1 if rank & (2**cube_dim) else 0 for cube_dim in range(num_cube_dims) ] _otf2.GlobalDefWriter_WriteCartCoordinate(glob_def_writer, 0, rank, cube_coordinates) _otf2.Archive_CloseGlobalDefWriter(archive, glob_def_writer) # write local mappings for MPI communicators and metrics */ # write local mappings for metrics, this is an identity map, just to write # something out _otf2.Archive_OpenDefFiles(archive) metric_map = _otf2.IdMap_Create(_otf2.ID_MAP_DENSE, NUM_OF_CLASSES) for c in range(NUM_OF_CLASSES): _otf2.IdMap_AddIdPair(metric_map, c, c) for rank in range(num_ranks): mpi_comm_map = _otf2.IdMap_Create(_otf2.ID_MAP_SPARSE, 2) # Each location uses its rank as the communicator id which maps to the global 0 */ _otf2.IdMap_AddIdPair(mpi_comm_map, rank, MPI_COMM_MPI_COMM_WORLD) _otf2.IdMap_AddIdPair(mpi_comm_map, rank + num_ranks, MPI_COMM_MPI_COMM_SELF) for thread in range(num_threads): # Open a definition writer, so the file is created. */ def_writer = _otf2.Archive_GetDefWriter( archive, locations[num_threads * rank + thread]) # Write metric mappings to local definitions. */ _otf2.DefWriter_WriteMappingTable(def_writer, _otf2.MAPPING_METRIC, metric_map) if otf2_MPI or otf2_HYBRID: # Write MPI Comm mappings to local definitions. */ _otf2.DefWriter_WriteMappingTable(def_writer, _otf2.MAPPING_COMM, mpi_comm_map) # Write clock offsets to local definitions. */ _otf2.DefWriter_WriteClockOffset(def_writer, 0, 0, 0.0) _otf2.DefWriter_WriteClockOffset(def_writer, t, 0, 0.0) _otf2.Archive_CloseDefWriter(archive, def_writer) _otf2.IdMap_Free(mpi_comm_map) _otf2.IdMap_Free(metric_map) _otf2.Archive_CloseDefFiles(archive) # Finalize. */ _otf2.Archive_Close(archive) _otf2.AttributeList_Delete(attributes) print("Done\n")