Skip to content
Snippets Groups Projects
Commit bf9a7530 authored by Jammer, Tim's avatar Jammer, Tim
Browse files

Merge branch 'devel-TJ' into 'main'

more work on infrastructure

See merge request !2
parents 28ca6aed 2b44084b
Branches
No related tags found
1 merge request!2more work on infrastructure
Showing
with 2216 additions and 78 deletions
......@@ -6,7 +6,7 @@ from scripts.Infrastructure.Template import InstructionBlock
class MPI_Call_Factory:
# one could generate the MPI Factory from the Standards JSON
def mpi_send(self, *args):
return MPI_Call("MPI_Send",
OrderedDict([("BUFFER", args[0]), ("COUNT", args[1]), ("DATATYPE", args[2]), ("SRC", args[3]),
......@@ -19,6 +19,7 @@ class MPI_Call_Factory:
("TAG", args[4]), ("COMM", args[5]), ("STATUS", args[6])]),
"1.0")
class Correct_Parameter:
# default params
buf_size = 10
......@@ -30,7 +31,7 @@ class Correct_Parameter:
def get_buffer_alloc(self):
b = InstructionBlock()
b.register_operation_all(("int* buf = (int*) malloc(%d* sizeof(%s));" % (self.buf_size, self.dtype[0])))
b.register_operation(("int* buf = (int*) malloc(%d* sizeof(%s));" % (self.buf_size, self.dtype[0])), kind='all')
return b
def get(self, param, func=None):
......
#! /usr/bin/python3
# ABC in python is abstract Base Class
from abc import ABC, abstractmethod
class ErrorGenerator(ABC):
"""
Abstract Class Overview:
The `ErrorGenerator` class is an abstract class defining the interface for error generators.
Methods:
- `__init__(self)`: Abstract method to initialize an instance of the ErrorGenerator class.
- `get_feature(self)`: Abstract method to get the features used in this generator (list).
- `get_num_errors(self)`: Abstract method to get the number of errors to produce in the normal mode.
- `get_num_errors_extended(self)`: Abstract method to get the number of errors in extended mode.
- `generate(self, i)`: Abstract method to generate error number i, returning a TemplateManager instance.
"""
@abstractmethod
def __init__(self):
pass
# get the Features used in this generator (list)
@abstractmethod
def get_feature(self):
"""
Abstract method to get the features used in this generator.
Returns:
list: List of features used.
"""
pass
# the number of errors to produce in the normal mode
@abstractmethod
def get_num_errors(self):
"""
Abstract method to get the number of errors to produce in the normal mode.
Returns:
int: Number of errors in normal mode.
"""
pass
@abstractmethod
def get_num_errors_extended(self):
"""
Abstract method to get the number of errors to produce in the extended mode (all possible combinations).
Returns:
int: Number of errors in extended mode.
"""
pass
@abstractmethod
def generate(self, i):
"""
Abstract method to generate error number i.
Parameters:
- i: Error number.
Returns:
TemplateManager: An instantiated and set up TemplateManager with the error case.
"""
pass
#! /usr/bin/python3
import inspect
import os
import importlib
import importlib.util
# for printing a nice progress bar
import tqdm
from scripts.Infrastructure.ErrorGenerator import ErrorGenerator
from scripts.Infrastructure.Variables import featurelist
# number of digits to use numbering filenames
digits_to_use = 3
def import_module(root, file):
full_fname = os.path.join(root, file)
name = file[:-3] # name without .py suffix
spec = importlib.util.spec_from_file_location(name, full_fname)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
class GeneratorManager:
def __init__(self, path):
self.generators = []
self.discover_generators(path)
self.case_names = {}
# discover all Error Generators
pass
def get_filename(self, case_name, suffix=".c"):
num = 0
if case_name in self.case_names:
num = self.case_names[case_name]
num = num + 1
self.case_names[case_name] = num
return case_name + "-" + str(num).zfill(digits_to_use) + suffix
def generate(self, outpath, filterlist_=None, print_progress_bar=True, overwrite=True,generate_full_set=False):
filterlist = filterlist_
if filterlist is None:
filterlist = featurelist
print("Generate Testcases")
# use generator if at least one feature of the generator matches the filterlist
generators_to_use = [g for g in self.generators if any(elem in filterlist for elem in g.get_feature())]
# collect total number of cases
total_cases = 0
for generator in generators_to_use:
num_errors_in_generator = 0
if generate_full_set:
num_errors_in_generator = generator.get_num_errors_extended()
else:
num_errors_in_generator = generator.get_num_errors()
total_cases = total_cases + num_errors_in_generator
# prints a nice progress bar
if print_progress_bar:
progress_bar = tqdm.tqdm(total=total_cases)
cases_generated = 0
for generator in generators_to_use:
num_errors_in_generator = 0
if generate_full_set:
num_errors_in_generator = generator.get_num_errors_extended()
else:
num_errors_in_generator = generator.get_num_errors()
for i in range(num_errors_in_generator):
result_error = generator.generate(i)
case_name = result_error.get_short_descr()
fname = self.get_filename(case_name)
full_name = os.path.join(outpath,fname)
if not overwrite and os.path.isfile(full_name):
assert False and "File Already exists"
with open(full_name, "w") as text_file:
text_file.write(str(result_error))
++cases_generated
if print_progress_bar:
progress_bar.update(1)
if print_progress_bar:
progress_bar.close()
pass
def discover_generators(self, path, print_discovery=True, skip_invalid=False):
if print_discovery:
print("Discover Generators:")
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith('.py'):
module = import_module(root, file)
for name, obj in inspect.getmembers(module):
# if it is a class derived from ErrorGenerator (and not the interface class itself)
if inspect.isclass(obj) and issubclass(obj, ErrorGenerator) and not obj is ErrorGenerator:
if print_discovery:
print("Found Generator %s" % name)
# instantiate the object
generator = obj()
valid = True
for feature in generator.get_feature():
if feature not in featurelist:
if print_discovery:
print("Generator has unknown feature: %s" % feature)
valid = False
if valid:
self.generators.append(generator)
else:
if not skip_invalid:
assert False and "Invalid Generator"
else:
pass # just skip
from scripts.Infrastructure.MPICall import MPI_Call
class InstructionBlock:
"""
Class Overview:
The `InstructionBlock` class represents a block of instructions in a Testcase (to be registered for a template).
First, the Instructions for all ranks are executed (in the order they are registered)
Then each thread executes the instructions registered to this specific rank
If one need a different Order: use multiple Instruction Blocks
Methods:
- `__init__(self)`: Initializes a new instance of the InstructionBlock class.
- `register_operation(self, op, kind='all')`: Registers an operation based on rank.
- `get_version(self)`: Retrieves required MPI version
- `__str__(self)`: Converts the InstructionBlock instance to a string, replacing placeholders.
"""
def __init__(self):
self.operations = {'all': [], 'not0': [], }
# TODO test if op also can be a list of operations
def register_operation(self, op, kind='all'):
"""
Registers an operation based on rank.
Parameters:
- op: The operation to register.
- kind: Rank to execute the operation ('all', 'not0', or integer).
- all: all Ranks execute this operation
- not0: all Ranks but the Root (rank 0) execute
- Or the integer of the rank that should execute
"""
if kind == 'all':
self.operations['all'].append(op)
elif kind == 'not0':
self.operations['not0'].append(op)
else:
as_int = int(kind) # will Raise ValueError if not integer
if as_int not in self.operations:
self.operations[as_int] = []
self.operations[as_int].append(op)
def get_version(self):
"""
Retrieves the minimum required MPI version.
Returns:
str: The MPI version used.
"""
max_v = "0.0"
for k, v in self.operations.items():
for op in v:
if isinstance(op, MPI_Call):
max_v = max(op.get_version(), max_v)
return max_v
def __str__(self):
"""
Converts the InstructionBlock instance to a string, replacing placeholders.
Returns:
str: The string representation of the InstructionBlock.
"""
result_str = ""
for key, val in self.operations.items():
if key == 'all':
for op in val:
result_str += str(op) + "\n"
elif key == 'not0':
if len(val) > 0:
result_str += "if (rank != 0) {\n"
for op in val:
result_str += str(op) + "\n"
result_str += "}\n"
else:
assert len(val) > 0
result_str += "if (rank == %d) {\n" % int(key)
for op in val:
result_str += str(op) + "\n"
result_str += "}\n"
return result_str
# THIS FILE IS NOT FOR PUBLICATION
# it is only used to generate the MPICallFactory code
import json
from scripts.Infrastructure.MPIAPIInfo.MPIAPIParameters import get_mpi_version_dict
template = """
def @{FUNC_KEY}@(self, *args):
return MPI_Call("@{FUNC_NAME}@", OrderedDict(@{PARAM_DICT}@), "@{VERSION}@")
"""
file_header="""#! /usr/bin/python3
from collections import OrderedDict
from scripts.Infrastructure.MPICall import MPI_Call
class MPI_Call_Factory:
"""
def main():
# read in the "official" standards json to get all mpi functions and there params
mpi_api_json_file = "scripts/Infrastructure/MPIAPIInfo/MPI_api.json"
output_file = "scripts/Infrastructure/MPICallFactory.py"
with open(mpi_api_json_file, "r") as file:
api_specs = json.load(file)
class_str = file_header
version_dict = get_mpi_version_dict()
for key, api_spec in api_specs.items():
spec = api_specs[key]
name = spec['name']
dict_str = "["
i = 0
for param in spec['parameters']:
if 'c_parameter' not in param['suppress']:
dict_str = dict_str + "(\"" + param['name'] + "\", args[" + str(i) + "]),"
i = i + 1
pass
dict_str = dict_str + "]"
ver = "4.0"
# everyting not in dict is 4.0
if (name in version_dict):
ver = version_dict[name]
function_def_str = (template.replace("@{FUNC_KEY}@", key)
.replace("@{FUNC_NAME}@", name)
.replace("@{PARAM_DICT}@", dict_str)
.replace("@{VERSION}@", ver))
class_str = class_str+ function_def_str
with open(output_file,"w") as outfile:
outfile.write(class_str)
# def mpi_send(self, *args):
# return MPI_Call("MPI_Send",
# OrderedDict([("BUFFER", args[0]), ("COUNT", args[1]), ("DATATYPE", args[2]), ("SRC", args[3]),
# ("TAG", args[4]), ("COMM", args[5])]),
# "1.0")
if __name__ == "__main__":
main()
# Originally from https://github.com/tudasc/mpi-arg-usage
# the mpi_version_dict listing the MPI Function Name and the MPI Version
mpi_version_dict = {'MPI_Abort': '1.0', 'MPI_Accumulate': '2.0', 'MPI_Add_error_class': '2.0',
'MPI_Add_error_code': '2.0',
'MPI_Add_error_string': '2.0', 'MPI_Address': '1.0', 'MPI_Allgather': '1.0',
'MPI_Allgatherv': '1.0',
'MPI_Alloc_mem': '2.0', 'MPI_Allreduce': '1.0', 'MPI_Alltoall': '1.0', 'MPI_Alltoallv': '1.0',
'MPI_Alltoallw': '2.0', 'MPI_Attr_delete': '1.0', 'MPI_Attr_get': '1.0', 'MPI_Attr_put': '1.0',
'MPI_Barrier': '1.0', 'MPI_Bcast': '1.0', 'MPI_Bsend': '1.0', 'MPI_Bsend_init': '1.0',
'MPI_Buffer_attach': '1.0', 'MPI_Buffer_detach': '1.0', 'MPI_Cancel': '1.0',
'MPI_Cart_coords': '1.0',
'MPI_Cart_create': '1.0', 'MPI_Cart_get': '1.0', 'MPI_Cart_map': '1.0', 'MPI_Cart_rank': '1.0',
'MPI_Cart_shift': '1.0', 'MPI_Cart_sub': '1.0', 'MPI_Cartdim_get': '1.0', 'MPI_Close_port': '2.0',
'MPI_Comm_accept': '2.0', 'MPI_Comm_c2f': '2.0', 'MPI_Comm_call_errhandler': '2.0',
'MPI_Comm_compare': '1.0', 'MPI_Comm_connect': '2.0', 'MPI_Comm_create': '1.0',
'MPI_Comm_create_errhandler': '2.0', 'MPI_Comm_create_group': '3.0',
'MPI_Comm_create_keyval': '2.0',
'MPI_Comm_delete_attr': '2.0', 'MPI_Comm_disconnect': '2.0', 'MPI_Comm_dup': '1.0',
'MPI_Comm_dup_with_info': '3.0', 'MPI_Comm_f2c': '2.0', 'MPI_Comm_free': '1.0',
'MPI_Comm_free_keyval': '2.0', 'MPI_Comm_get_attr': '2.0', 'MPI_Comm_get_errhandler': '2.0',
'MPI_Comm_get_info': '3.0', 'MPI_Comm_get_name': '2.0', 'MPI_Comm_get_parent': '2.0',
'MPI_Comm_group': '1.0', 'MPI_Comm_idup': '3.0', 'MPI_Comm_join': '2.0', 'MPI_Comm_rank': '1.0',
'MPI_Comm_remote_group': '1.0', 'MPI_Comm_remote_size': '1.0', 'MPI_Comm_set_attr': '2.0',
'MPI_Comm_set_errhandler': '2.0', 'MPI_Comm_set_info': '3.0', 'MPI_Comm_set_name': '2.0',
'MPI_Comm_size': '1.0', 'MPI_Comm_spawn': '2.0', 'MPI_Comm_spawn_multiple': '2.0',
'MPI_Comm_split': '1.0',
'MPI_Comm_split_type': '3.0', 'MPI_Comm_test_inter': '1.0', 'MPI_Compare_and_swap': '3.0',
'MPI_Dims_create': '1.0', 'MPI_Dist_graph_create': '2.2', 'MPI_Dist_graph_create_adjacent': '2.2',
'MPI_Dist_graph_neighbors': '2.2', 'MPI_Dist_graph_neighbors_count': '2.2',
'MPI_Errhandler_create': '1.0',
'MPI_Errhandler_free': '1.0', 'MPI_Errhandler_get': '1.0', 'MPI_Errhandler_set': '1.0',
'MPI_Error_class': '1.0', 'MPI_Error_string': '1.0', 'MPI_Exscan': '2.0', 'MPI_Fetch_and_op': '3.0',
'MPI_File_c2f': '2.0', 'MPI_File_call_errhandler': '2.0', 'MPI_File_close': '2.0',
'MPI_File_create_errhandler': '2.0', 'MPI_File_delete': '2.0', 'MPI_File_f2c': '2.0',
'MPI_File_get_amode': '2.0', 'MPI_File_get_atomicity': '2.0', 'MPI_File_get_byte_offset': '2.0',
'MPI_File_get_errhandler': '2.0', 'MPI_File_get_group': '2.0', 'MPI_File_get_info': '2.0',
'MPI_File_get_position': '2.0', 'MPI_File_get_position_shared': '2.0', 'MPI_File_get_size': '2.0',
'MPI_File_get_type_extent': '2.0', 'MPI_File_get_view': '2.0', 'MPI_File_iread': '2.0',
'MPI_File_iread_all': '3.1', 'MPI_File_iread_at': '2.0', 'MPI_File_iread_at_all': '3.1',
'MPI_File_iread_shared': '2.0', 'MPI_File_iwrite': '2.0', 'MPI_File_iwrite_all': '3.1',
'MPI_File_iwrite_at': '2.0', 'MPI_File_iwrite_at_all': '3.1', 'MPI_File_iwrite_shared': '2.0',
'MPI_File_open': '2.0', 'MPI_File_preallocate': '2.0', 'MPI_File_read': '2.0',
'MPI_File_read_all': '2.0',
'MPI_File_read_all_begin': '2.0', 'MPI_File_read_all_end': '2.0', 'MPI_File_read_at': '2.0',
'MPI_File_read_at_all': '2.0', 'MPI_File_read_at_all_begin': '2.0',
'MPI_File_read_at_all_end': '2.0',
'MPI_File_read_ordered': '2.0', 'MPI_File_read_ordered_begin': '2.0',
'MPI_File_read_ordered_end': '2.0',
'MPI_File_read_shared': '2.0', 'MPI_File_seek': '2.0', 'MPI_File_seek_shared': '2.0',
'MPI_File_set_atomicity': '2.0', 'MPI_File_set_errhandler': '2.0', 'MPI_File_set_info': '2.0',
'MPI_File_set_size': '2.0', 'MPI_File_set_view': '2.0', 'MPI_File_sync': '2.0',
'MPI_File_write': '2.0',
'MPI_File_write_all': '2.0', 'MPI_File_write_all_begin': '2.0', 'MPI_File_write_all_end': '2.0',
'MPI_File_write_at': '2.0', 'MPI_File_write_at_all': '2.0', 'MPI_File_write_at_all_begin': '2.0',
'MPI_File_write_at_all_end': '2.0', 'MPI_File_write_ordered': '2.0',
'MPI_File_write_ordered_begin': '2.0',
'MPI_File_write_ordered_end': '2.0', 'MPI_File_write_shared': '2.0', 'MPI_Finalize': '1.0',
'MPI_Finalized': '2.0', 'MPI_Free_mem': '2.0', 'MPI_Gather': '1.0', 'MPI_Gatherv': '1.0',
'MPI_Get': '2.0',
'MPI_Get_accumulate': '3.0', 'MPI_Get_address': '2.0', 'MPI_Get_count': '1.0',
'MPI_Get_elements': '1.0',
'MPI_Get_elements_x': '3.0', 'MPI_Get_library_version': '3.0', 'MPI_Get_processor_name': '1.0',
'MPI_Get_version': '1.0', 'MPI_Graph_create': '1.0', 'MPI_Graph_get': '1.0', 'MPI_Graph_map': '1.0',
'MPI_Graph_neighbors': '1.0', 'MPI_Graph_neighbors_count': '1.0', 'MPI_Graphdims_get': '1.0',
'MPI_Grequest_complete': '2.0', 'MPI_Grequest_start': '2.0', 'MPI_Group_c2f': '2.0',
'MPI_Group_compare': '1.0', 'MPI_Group_difference': '1.0', 'MPI_Group_excl': '1.0',
'MPI_Group_f2c': '2.0',
'MPI_Group_free': '1.0', 'MPI_Group_incl': '1.0', 'MPI_Group_intersection': '1.0',
'MPI_Group_range_excl': '1.0', 'MPI_Group_range_incl': '1.0', 'MPI_Group_rank': '1.0',
'MPI_Group_size': '1.0', 'MPI_Group_translate_ranks': '1.0', 'MPI_Group_union': '1.0',
'MPI_Iallgather': '3.0', 'MPI_Iallgatherv': '3.0', 'MPI_Iallreduce': '3.0', 'MPI_Ialltoall': '3.0',
'MPI_Ialltoallv': '3.0', 'MPI_Ialltoallw': '3.0', 'MPI_Ibarrier': '3.0', 'MPI_Ibcast': '3.0',
'MPI_Ibsend': '1.0', 'MPI_Iexscan': '3.0', 'MPI_Igather': '3.0', 'MPI_Igatherv': '3.0',
'MPI_Improbe': '3.0', 'MPI_Imrecv': '3.0', 'MPI_Ineighbor_allgather': '3.0',
'MPI_Ineighbor_allgatherv': '3.0', 'MPI_Ineighbor_alltoall': '3.0',
'MPI_Ineighbor_alltoallv': '3.0',
'MPI_Ineighbor_alltoallw': '3.0', 'MPI_Info_c2f': '2.0', 'MPI_Info_create': '2.0',
'MPI_Info_delete': '2.0',
'MPI_Info_dup': '2.0', 'MPI_Info_f2c': '2.0', 'MPI_Info_free': '2.0', 'MPI_Info_get': '2.0',
'MPI_Info_get_nkeys': '2.0', 'MPI_Info_get_nthkey': '2.0', 'MPI_Info_get_valuelen': '2.0',
'MPI_Info_set': '2.0', 'MPI_Init': '1.0', 'MPI_Init_thread': '2.0', 'MPI_Initialized': '1.0',
'MPI_Intercomm_create': '1.0', 'MPI_Intercomm_merge': '1.0', 'MPI_Iprobe': '1.0',
'MPI_Irecv': '1.0',
'MPI_Ireduce': '3.0', 'MPI_Ireduce_scatter': '3.0', 'MPI_Ireduce_scatter_block': '3.0',
'MPI_Irsend': '1.0',
'MPI_Is_thread_main': '2.0', 'MPI_Iscan': '3.0', 'MPI_Iscatter': '3.0', 'MPI_Iscatterv': '3.0',
'MPI_Isend': '1.0', 'MPI_Issend': '1.0', 'MPI_Keyval_create': '1.0', 'MPI_Keyval_free': '1.0',
'MPI_Lookup_name': '2.0', 'MPI_Mprobe': '3.0', 'MPI_Mrecv': '3.0', 'MPI_Neighbor_allgather': '3.0',
'MPI_Neighbor_allgatherv': '3.0', 'MPI_Neighbor_alltoall': '3.0', 'MPI_Neighbor_alltoallv': '3.0',
'MPI_Neighbor_alltoallw': '3.0', 'MPI_Op_c2f': '2.0', 'MPI_Op_commutative': '2.2',
'MPI_Op_create': '1.0',
'MPI_Op_f2c': '2.0', 'MPI_Op_free': '1.0', 'MPI_Open_port': '2.0', 'MPI_Pack': '1.0',
'MPI_Pack_external': '2.0', 'MPI_Pack_external_size': '2.0', 'MPI_Pack_size': '1.0',
'MPI_Pcontrol': '1.0',
'MPI_Probe': '1.0', 'MPI_Publish_name': '2.0', 'MPI_Put': '2.0', 'MPI_Query_thread': '2.0',
'MPI_Raccumulate': '3.0', 'MPI_Recv': '1.0', 'MPI_Recv_init': '1.0', 'MPI_Reduce': '1.0',
'MPI_Reduce_local': '2.2', 'MPI_Reduce_scatter': '1.0', 'MPI_Reduce_scatter_block': '2.2',
'MPI_Register_datarep': '2.0', 'MPI_Request_c2f': '2.0', 'MPI_Request_f2c': '2.0',
'MPI_Request_free': '1.0', 'MPI_Request_get_status': '2.0', 'MPI_Rget': '3.0',
'MPI_Rget_accumulate': '3.0',
'MPI_Rput': '3.0', 'MPI_Rsend': '1.0', 'MPI_Rsend_init': '1.0', 'MPI_Scan': '1.0',
'MPI_Scatter': '1.0',
'MPI_Scatterv': '1.0', 'MPI_Send': '1.0', 'MPI_Send_init': '1.0', 'MPI_Sendrecv': '1.0',
'MPI_Sendrecv_replace': '1.0', 'MPI_Sizeof': '2.0', 'MPI_Ssend': '1.0', 'MPI_Ssend_init': '1.0',
'MPI_Start': '1.0', 'MPI_Startall': '1.0', 'MPI_Status_c2f': '2.0', 'MPI_Status_f2c': '2.0',
'MPI_Status_set_cancelled': '2.0', 'MPI_Status_set_elements': '2.0',
'MPI_Status_set_elements_x': '3.0',
'MPI_Test': '1.0', 'MPI_Test_cancelled': '1.0', 'MPI_Testall': '1.0', 'MPI_Testany': '1.0',
'MPI_Testsome': '1.0', 'MPI_Topo_test': '1.0', 'MPI_Type_c2f': '2.0', 'MPI_Type_commit': '1.0',
'MPI_Type_contiguous': '1.0', 'MPI_Type_create_darray': '2.0', 'MPI_Type_create_f90_complex': '2.0',
'MPI_Type_create_f90_integer': '2.0', 'MPI_Type_create_f90_real': '2.0',
'MPI_Type_create_hindexed': '2.0',
'MPI_Type_create_hindexed_block': '3.0', 'MPI_Type_create_hvector': '2.0',
'MPI_Type_create_indexed_block': '2.0', 'MPI_Type_create_keyval': '2.0',
'MPI_Type_create_resized': '2.0',
'MPI_Type_create_struct': '2.0', 'MPI_Type_create_subarray': '2.0', 'MPI_Type_delete_attr': '2.0',
'MPI_Type_dup': '2.0', 'MPI_Type_extent': '1.0', 'MPI_Type_f2c': '2.0', 'MPI_Type_free': '1.0',
'MPI_Type_free_keyval': '2.0', 'MPI_Type_get_attr': '2.0', 'MPI_Type_get_contents': '2.0',
'MPI_Type_get_envelope': '2.0', 'MPI_Type_get_extent': '2.0', 'MPI_Type_get_extent_x': '3.0',
'MPI_Type_get_name': '2.0', 'MPI_Type_get_true_extent': '2.0', 'MPI_Type_get_true_extent_x': '3.0',
'MPI_Type_hindexed': '1.0', 'MPI_Type_hvector': '1.0', 'MPI_Type_indexed': '1.0',
'MPI_Type_lb': '1.0',
'MPI_Type_match_size': '2.0', 'MPI_Type_set_attr': '2.0', 'MPI_Type_set_name': '2.0',
'MPI_Type_size': '1.0', 'MPI_Type_size_x': '3.0', 'MPI_Type_struct': '1.0', 'MPI_Type_ub': '1.0',
'MPI_Type_vector': '1.0', 'MPI_Unpack': '1.0', 'MPI_Unpack_external': '2.0',
'MPI_Unpublish_name': '2.0',
'MPI_Wait': '1.0', 'MPI_Waitall': '1.0', 'MPI_Waitany': '1.0', 'MPI_Waitsome': '1.0',
'MPI_Win_allocate': '3.0', 'MPI_Win_allocate_shared': '3.0', 'MPI_Win_attach': '3.0',
'MPI_Win_c2f': '2.0',
'MPI_Win_call_errhandler': '2.0', 'MPI_Win_complete': '2.0', 'MPI_Win_create': '2.0',
'MPI_Win_detach': '3.0', 'MPI_Win_create_dynamic': '3.0', 'MPI_Win_create_errhandler': '2.0',
'MPI_Win_create_keyval': '2.0', 'MPI_Win_delete_attr': '2.0', 'MPI_Win_f2c': '2.0',
'MPI_Win_fence': '2.0',
'MPI_Win_free': '2.0', 'MPI_Win_free_keyval': '2.0', 'MPI_Win_get_attr': '2.0',
'MPI_Win_get_errhandler': '2.0', 'MPI_Win_get_group': '2.0', 'MPI_Win_get_info': '3.0',
'MPI_Win_get_name': '2.0', 'MPI_Win_lock': '2.0', 'MPI_Win_lock_all': '3.0', 'MPI_Win_post': '2.0',
'MPI_Win_set_attr': '2.0', 'MPI_Win_set_errhandler': '2.0', 'MPI_Win_flush': '3.0',
'MPI_Win_flush_all': '3.0', 'MPI_Win_flush_local': '3.0', 'MPI_Win_flush_local_all': '3.0',
'MPI_Win_set_info': '3.0', 'MPI_Win_set_name': '2.0', 'MPI_Win_shared_query': '3.0',
'MPI_Win_start': '2.0',
'MPI_Win_sync': '3.0', 'MPI_Win_test': '2.0', 'MPI_Win_unlock': '2.0', 'MPI_Win_unlock_all': '3.0',
'MPI_Win_wait': '2.0', 'MPI_Wtick': '1.0', 'MPI_Wtime': '1.0', 'MPI_User_function': '1.0',
'MPI_Copy_function': '1.0', 'MPI_Delete_function': '1.0', 'MPI Comm errhandler fn': '2.0',
'MPI_Comm_copy_attr_function': '2.0', 'MPI_Comm_delete_attr_function': '2.0',
'MPI_Grequest_query_function': '2.0', 'MPI_Grequest_free_function': '2.0',
'MPI_Grequest_cancel_function': '2.0', 'MPI_Comm_errhandler_function': '2.2', 'MPI_DUP_FN': '2.2',
'MPI_T_pvar_handle_alloc': '3.0', 'MPI_T_pvar_start': '3.0', 'MPI_T_pvar_read': '3.0',
'MPI_T_pvar_write': '3.0', 'MPI_T_pvar_reset': '3.0', 'MPI_T_pvar_readreset': '3.0',
'MPI_T_category_get_num': '3.0', 'MPI_T_category_get_info': '3.0',
'MPI_T_category_get_cvars': '3.0',
'MPI_T_category_get_pvars': '3.0', 'MPI_T_category_get_categories': '3.0',
'MPI_T_category_changed': '3.0',
'MPI_T_cvar_get_index': '3.0', 'MPI_T_pvar_get_index': '3.0', 'MPI_T_category_get_index': '3.0',
'MPI_T_pvar_handle_free': '3.0', 'MPI_T_pvar_stop': '3.0', 'MPI_T_pvar_session_free': '3.0',
'MPI_T_cvar_get_num': '3.0', 'MPI_T_init_thread': '3.0', 'MPI_T_pvar_session_create': '3.0',
'MPI_T_enum_get_info': '3.0', 'MPI_T_enum_get_item': '3.0', 'MPI_T_finalize': '3.0',
'MPI_T_cvar_get_info': '3.0', 'MPI_T_cvar_handle_alloc': '3.0', 'MPI_T_cvar_handle_free': '3.0',
'MPI_T_cvar_read': '3.0', 'MPI_T_cvar_write': '3.0', 'MPI_T_pvar_get_num': '3.0',
'MPI_T_pvar_get_info': '3.0', 'MPI_Aint_add': '3.1', 'MPI_Aint_diff': '3.1'}
def get_mpi_version_dict():
return mpi_version_dict
This diff is collapsed.
#! /usr/bin/python3
from scripts.Infrastructure.InstructionBlock import InstructionBlock
from scripts.Infrastructure.MPICall import MPI_Call
template = """// @{generatedby}@
......@@ -7,7 +7,7 @@ template = """// @{generatedby}@
Description: @{desc}@
Version of MPI: @{vers}
Version of MPI: @{version}@
BEGIN_MPI_FEATURES
P2P!basic: @{p2pfeature}@
......@@ -21,7 +21,7 @@ BEGIN_MPI_FEATURES
END_MPI_FEATURES
BEGIN_MBI_TESTS
$ mpirun -np 2 ${EXE}
$ mpirun -np @{min_num_ranks}@ ${EXE}
| @{outcome}@
| @{errormsg}@
END_MBI_TESTS
......@@ -35,109 +35,123 @@ int main(int argc, char **argv) {
int nprocs = -1;
int rank = -1;
MPI_Init(&argc, &argv);
// @{mpi_init}@ // One could also templte this
@{mpi_init}@
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
//@{num_ranks_check}@ // One could also templte this
if (nprocs < 2)
if (nprocs < @{min_num_ranks}@)
printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
@{test_code}@
//@{mpi_finalize}@// One could also templte this
MPI_Finalize();
@{mpi_finalize}@
printf("Rank %d finished normally\\n", rank);
return 0;
}
"""
template_instruction_block = """
if (rank == 0) {
@{operation_rank0}@
}else {
@{operation_rank1}@
}
@{operation_all}@
init_thread_template = """int provided;
MPI_Init_thread(&argc, &argv, @{thread_level}@, &provided);
if (@{thread_level}@ < provided)
printf("MBI ERROR: The MPI Implementation does not provide the required thread level!\\n");
"""
class TemplateManager:
def __init__(self):
self._descr = ""
"""
Class Overview:
The `TemplateManager` class is responsible for managing MPI error case templates.
Methods:
- `__init__(self)`: Initializes a new instance of the TemplateManager class.
- `__str__(self)`: Converts the TemplateManager instance to a string, replacing placeholders.
- `register_instruction_block(self, block)`: Registers an instruction block with the template.
- `get_version(self)`: Retrieves required MPI version.
- `set_description(self, descr_short, descr_full)`: Sets the short and full descriptions.
- `get_short_descr(self)`: Retrieves the short description .
"""
def __init__(self, min_ranks=2, thread_level=None, has_finalize=True, has_init=True):
"""
Initialize the TemplateManager
Parameters:
min_ranks (int): the number of MPI ranks to use for this case
thread_level : the MPI Thread Level to use (None means use MPI_Init instead of Init_Thread)
has_finalize (bool) : if call to MPI Finalize should be included
has_init (bool) : if call to MPI Init should be included
"""
self._descr_full = ""
self._descr_short = ""
self._blocks = []
self._thread_level = thread_level
self._min_ranks = min_ranks
self._has_finalize = has_finalize
self._has_init = has_init
def __str__(self):
"""
Converts the TemplateManager to a string, replacing placeholders.
"""
version = self.get_version()
block_string = ""
for block in self._blocks:
block_string += str(block) + "\n"
init_string = ""
if self._has_init:
if self._thread_level == None:
init_string = "MPI_Init(&argc, &argv);"
else:
init_string = init_thread_template.replace("@{thread_level}@", self._thread_level)
finalize_string = ""
if self._has_finalize:
finalize_string = "MPI_Finalize();"
return (template
.replace("@{desc}@", self._descr)
.replace("@{min_num_ranks}@", str(self._min_ranks))
.replace("@{mpi_init}@", init_string)
.replace("@{mpi_finalize}@", finalize_string)
.replace("@{desc}@", self._descr_full)
.replace("@{version}@", version)
.replace("@{test_code}@", block_string))
def register_instruction_block(self, block):
"""
Registers an instruction block with the template.
Parameters:
- block: The instruction block to register.
"""
self._blocks.append(block)
def get_version(self):
"""
Retrieves the minimum required MPI version.
Returns:
str: The MPI version used.
"""
max_v = "0.0"
for block in self._blocks:
assert isinstance(block, InstructionBlock)
max_v = max(block.get_version(), max_v)
return max_v
def set_description(self, descr):
self._descr = descr
class InstructionBlock:
def __init__(self):
self.operations_0 = []
self.operations_1 = []
self.operations_all = []
def register_operation_all(self, op):
self.operations_all.append(op)
pass
def register_operation_0(self, op):
self.operations_0.append(op)
pass
def register_operation_1(self, op):
self.operations_1.append(op)
pass
def register_operation(self, op, kind='all'):
if kind == 'all':
self.register_operation_all(op)
elif kind == '0' or kind == 0:
self.register_operation_0(op)
elif kind == '1' or kind == 1:
self.register_operation_1(op)
else:
assert False
def get_version(self):
max_v = "0.0"
for op in self.operations_0 + self.operations_1 + self.operations_all:
if isinstance(op, MPI_Call):
max_v = max(op.get_version(), max_v)
return max_v
def set_description(self, descr_short, descr_full):
"""
Sets the short and full descriptions for the template.
Parameters:
- descr_short: The short description for use as the filename.
- descr_full: The full description for use in the header.
"""
self._descr_full = descr_full
self._descr_short = descr_short
# TODO one could write a function to check if short desc = filename is conforming with the naming sceme
def __str__(self):
op_0_string = ""
for op in self.operations_0:
op_0_string += str(op) + "\n"
op_1_string = ""
for op in self.operations_1:
op_1_string += str(op) + "\n"
op_all_string = ""
for op in self.operations_all:
op_all_string += str(op) + "\n"
return (template_instruction_block
.replace("@{operation_rank0}@", op_0_string)
.replace("@{operation_rank1}@", op_1_string)
.replace("@{operation_all}@", op_all_string))
def get_short_descr(self):
"""
Retrieves the short description to use as a filename.
Returns:
str: The short description.
"""
assert self._descr_short != ""
return self._descr_short
#! /usr/bin/python3
# The 'Magic' Comment denoting where the Error is in a testcase
ERROR_MARKER_COMMENT = "/*MBBERROR*/"
# The List of Features considered
featurelist = ["P2P", "COLL", "RMA", "TOOL"]
#! /usr/bin/python3
from scripts.Infrastructure.ErrorGenerator import ErrorGenerator
from scripts.Infrastructure.InstructionBlock import InstructionBlock
from scripts.Infrastructure.MPICallFactory import MPI_Call_Factory
from scripts.Infrastructure.CorrectParameter import Correct_Parameter,get_matching_recv
from scripts.Infrastructure.Template import TemplateManager
class Invalid_negative_rank_error(ErrorGenerator):
invalid_ranks = ["-1", "size", "NULL", "MPI_PROC_NULL"]
def __init__(self):
pass
def get_num_errors(self):
return len(self.invalid_ranks)
# the number of errors to produce in the extended mode (all possible combinations)
def get_num_errors_extended(self):
return len(self.invalid_ranks)
def get_feature(self):
return ["P2P"]
def generate(self, i):
tm = TemplateManager()
correct_params = Correct_Parameter()
tm.set_description("InvalidParam-Rank-MPI_Send", "Invalid Rank: %s" % self.invalid_ranks[i])
# include the buffer allocation in the template (all ranks execute it)
tm.register_instruction_block(correct_params.get_buffer_alloc())
send = MPI_Call_Factory().mpi_send(
correct_params.get("BUFFER"),
correct_params.get("COUNT"),
correct_params.get("DATATYPE"),
self.invalid_ranks[i], # invalid rank
correct_params.get("TAG"),
correct_params.get("COMM"),
)
send.set_has_error()
b = InstructionBlock()
# only rank 0 execute the send
b.register_operation(send, 0)
# only rank 1 execute the recv
b.register_operation(get_matching_recv(send), 1)
tm.register_instruction_block(b)
return tm
#! /usr/bin/python3
from scripts.Infrastructure.GeneratorManager import GeneratorManager
if __name__ == "__main__":
gm = GeneratorManager("./errors")
gm.generate("../gencodes")
pass
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment