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

merge into devel

parents cc0d2478 0a95320e
No related branches found
No related tags found
1 merge request!3more work on infrastructure II
#! /usr/bin/python3
alloc_template = """
@{NAME}@ = (@{TYPE}@*) @{FUNCTION}@(@{NUM}@ @{SEP}@ sizeof(@{TYPE}@));
"""
"""
Class Overview:
The `AllocCall` class is a helper for creationg allocation calls (with malloc or calloc)
Methods:
- `__init__(self)`: Initializes a new Alloc Call
- `__str__(self)`: Converts the AllocCall instance to a string, replacing placeholders.
- `set_num_elements(self, num_elements)`: Sets number of elements to allocate
- `set_type(self, type)`: Sets the type of allocated elements
- `set_name(self, name)`: Sets the name of allocated variable
- `set_use_calloc(self)`: Use calloc
- `set_use_malloc(self)`: Use malloc
"""
class AllocCall:
def __init__(self, type, num_elements, name="buf", use_malloc=False):
"""
Creates a New allocation Call
Args:
type: Type to allocate (int not MPI_INT)
num_elements: number of buffer elements
name: name of buffer variable
use_malloc: True: use Malloc, False: use calloc for allocation
"""
self._use_malloc = use_malloc
self._type = type
self._num_elements = num_elements
self._name = name
def __str__(self):
if self._use_malloc:
delim = '*'
func = "malloc"
else:
delim = ','
func = "calloc"
return (alloc_template
.replace("@{NAME}@", self._name)
.replace("@{TYPE}@", self._type)
.replace("@{FUNCTION}@", func)
.replace("@{NUM}@", self._num_elements)
.replace("@{SEP}", delim))
def set_num_elements(self, num_elements):
self._num_elements = num_elements
def set_name(self, name):
self._name = name
def set_type(self, type):
self._type = type
def set_use_malloc(self):
self._use_malloc = True
def set_use_calloc(self):
self._use_malloc = False
def get_num_elements(self):
return self._num_elements
def get_name(self):
return self._name
def get_type(self):
return self._type
def get_use_malloc(self):
return self._use_malloc
def get_free(alloc_call):
assert isinstance(alloc_call, AllocCall)
return "free(" + alloc_call.get_name() + ");\n"
...@@ -5,23 +5,29 @@ from scripts.Infrastructure.MPICall import MPI_Call ...@@ -5,23 +5,29 @@ from scripts.Infrastructure.MPICall import MPI_Call
from scripts.Infrastructure.Template import InstructionBlock from scripts.Infrastructure.Template import InstructionBlock
class CorrectParameterFactory:
from scripts.Infrastructure.MPICallFactory import MPI_Call_Factory
from scripts.Infrastructure.AllocCall import AllocCall
class CorrectParameterFactory: class CorrectParameterFactory:
# default params # default params
buf_size = 10 buf_size = 10
dtype = ['int', 'MPI_INT'] dtype = ['int', 'MPI_INT']
tag = 0 tag = 0
buf_var_name= "buf"
def __init__(self): def __init__(self):
pass pass
def get_buffer_alloc(self): def get_buffer_alloc(self):
b = InstructionBlock() b = InstructionBlock()
b.register_operation(("int* buf = (int*) malloc(%d* sizeof(%s));" % (self.buf_size, self.dtype[0])), kind='all') b.register_operation(AllocCall(self.dtype[0], self.buf_size, self.buf_var_name, use_malloc=False), kind='all')
return b return b
def get(self, param, func=None): def get(self, param, func=None):
if param == "BUFFER" or param == "buf": if param == "BUFFER" or param == "buf":
return "buf" return self.buf_var_name
if param == "COUNT" or param == "count": if param == "COUNT" or param == "count":
return str(self.buf_size) return str(self.buf_size)
if param == "DATATYPE" or param == "datatype": if param == "DATATYPE" or param == "datatype":
......
...@@ -16,8 +16,17 @@ class InstructionBlock: ...@@ -16,8 +16,17 @@ class InstructionBlock:
- `__str__(self)`: Converts the InstructionBlock instance to a string, replacing placeholders. - `__str__(self)`: Converts the InstructionBlock instance to a string, replacing placeholders.
""" """
def __init__(self): def __init__(self, name=None):
"""
Initialize an empty InstructionBlock
Parameters:
- name (str): The name of the block (for referencing this block with the template Manager)
May be None, does not influence the code generated
"""
self.operations = {'all': [], 'not0': [], } self.operations = {'all': [], 'not0': [], }
assert not isinstance(name, int)
self.name = name
# TODO test if op also can be a list of operations # TODO test if op also can be a list of operations
def register_operation(self, op, kind='all'): def register_operation(self, op, kind='all'):
...@@ -79,3 +88,37 @@ class InstructionBlock: ...@@ -79,3 +88,37 @@ class InstructionBlock:
result_str += "}\n" result_str += "}\n"
return result_str return result_str
def get_operation(self, kind=all, index=0):
"""
Retrieve the operation registered. will Raise IndexError if not present
Parameters:
- kind ('all','not0' or integer): which ranks should execute the operation
- index (int): the index of the operation within the given kind
Returns:
str: The operation specified by kind and index
"""
return self.operations[kind][index]
def replace_operation(self, op, kind=all, index=0):
"""
Replace the operation registered. will Raise IndexError if not present
Parameters:
- op (str or MPICall) the new operation
- kind ('all','not0' or integer): which ranks should execute the operation
- index (int): the index of the operation within the given kind
"""
if len(self.operations[kind]) >= index:
raise IndexError("Operation Not Found")
self.operations[kind][index] = op
def remove_operation(self, kind=all, index=0):
"""
Removes the operation registered. will Raise IndexError if not present
Parameters:
- kind ('all','not0' or integer): which ranks should execute the operation
- index (int): the index of the operation within the given kind
"""
if len(self.operations[kind]) >= index:
raise IndexError("Operation Not Found")
del self.operations[kind][index]
...@@ -155,3 +155,89 @@ class TemplateManager: ...@@ -155,3 +155,89 @@ class TemplateManager:
""" """
assert self._descr_short != "" assert self._descr_short != ""
return self._descr_short return self._descr_short
def get_block(self, block_name=None, idx=None):
"""
Retrieves the given Instruction Block Either by name or by index
Raises IndexError if not the specified block is not found
Raises IndexError if multiple Blocks with the given name are found
Raises ValueError if Both a block name and index are given (or none is given)
Args:
block_name (str): The name of the InstructionBlock to receive
idx (int): index of the InstructionBlock to retrieve
Returns:
the specified Block
"""
if block_name is not None:
if idx is not None:
raise ValueError("Both block name and index are given")
to_return = [b for b in self._blocks if b.name == block_name]
if len(to_return) == 0:
raise IndexError("Block Not Found")
if len(to_return) > 0:
raise IndexError("Multiple Blocks Found")
return to_return[0]
if idx is not None:
if block_name is not None:
raise ValueError("Both block name and index are given")
return self._blocks[idx]
raise ValueError("Neither Both block name nor index is given")
def remove_block(self, block_name=None, idx=None):
"""
Removes the given Instruction Block Either by name or by index
Raises IndexError if not the specified block is not found
Raises IndexError if multiple Blocks with the given name are found
Raises ValueError if Both a block name and index are given (or none is given)
Args:
block_name (str): The name of the InstructionBlock to receive
idx (int): index of the InstructionBlock to retrieve
"""
if block_name is not None:
if idx is not None:
raise ValueError("Both block name and index are given")
to_return = [b for b in self._blocks if b.name == block_name]
if len(to_return) == 0:
raise IndexError("Block Not Found")
if len(to_return) > 0:
raise IndexError("Multiple Blocks Found")
self._blocks.remove(to_return[0])
if idx is not None:
if block_name is not None:
raise ValueError("Both block name and index are given")
del self._blocks[idx]
raise ValueError("Neither Both block name nor index is given")
def replace_block(self, new_block, block_name=None, idx=None):
"""
Removes the given Instruction Block Either by name or by index
Raises IndexError if not the specified block is not found
Raises IndexError if multiple Blocks with the given name are found
Raises ValueError if Both a block name and index are given (or none is given)
Args:
new_block (InstructionBlock): The new Block to replace the old one (does not need to have the same name)
block_name (str): The name of the InstructionBlock to receive
idx (int): index of the InstructionBlock to retrieve
"""
assert isinstance(new_block, InstructionBlock)
if block_name is not None:
if idx is not None:
raise ValueError("Both block name and index are given")
to_return = [b for b in self._blocks if b.name == block_name]
if len(to_return) == 0:
raise IndexError("Block Not Found")
if len(to_return) > 0:
raise IndexError("Multiple Blocks Found")
self._blocks[self._blocks.index(to_return[0])] = new_block
if idx is not None:
if block_name is not None:
raise ValueError("Both block name and index are given")
self._blocks[idx] = new_block
raise ValueError("Neither Both block name nor index is given")
#! /usr/bin/python3
from scripts.Infrastructure.InstructionBlock import InstructionBlock
from scripts.Infrastructure.MPICall import MPI_Call
from scripts.Infrastructure.Template import TemplateManager
"""
Contructs a default template for the given mpi function
Returns:
TemplateManager Initialized with a default template
The function is contained in a block named MPICALL with seperate calls for rank 1 and 2)
"""
def get_default_template(mpi_func):
tm = TemplateManager()
cf = Co
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment