Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Task #867

Draft
wants to merge 25 commits into
base: devel
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3006d1c
add karim's presentation
MostafaMamouni Apr 5, 2021
1af0440
WSL bug temporary fix
MenoIy Apr 7, 2021
d871380
create task decorator
MenoIy Apr 7, 2021
71d04fd
add task decorator to __all__
MenoIy Apr 7, 2021
2c7f193
manage decorator task in syntactic
MenoIy Apr 7, 2021
1810937
Merge branch 'master' into task_printer
MostafaMamouni Apr 8, 2021
61c1aeb
basic printer
MostafaMamouni Apr 8, 2021
b084a42
print depend clause
MostafaMamouni Apr 9, 2021
aebf089
Merge branch 'master' into task_printer
MostafaMamouni Apr 9, 2021
4bbfb8d
commit progress
MenoIy Apr 12, 2021
ed06c0b
Merge remote-tracking branch 'origin/task_printer' into task
MenoIy Apr 12, 2021
905154b
return func res
MenoIy Apr 12, 2021
07e4200
correct printer
MenoIy Apr 12, 2021
0a68218
update presentation
MenoIy Apr 12, 2021
cd89b8e
collect additional informations from decorator task (threads num)
MenoIy Apr 22, 2021
ec25d21
update doc and add arg for task decorator
MenoIy Apr 22, 2021
258cf42
update printer
MenoIy Apr 22, 2021
cdc9e87
create class TaskMaster and add new element to class task
MenoIy Apr 22, 2021
46f6471
add floor conversion to sympy helper
MenoIy Apr 22, 2021
23aa1fe
update semantic
MenoIy Apr 22, 2021
322cf73
Merge branch 'master' into task
MenoIy Apr 22, 2021
79a490e
remove non used element
MenoIy Apr 22, 2021
de7d87f
raise non impelemented error when assign task with no results to var…
MenoIy Apr 22, 2021
20eb865
correct some grammar / typo
MenoIy Apr 26, 2021
418ea77
always collect array as shareds for tasks
MenoIy Apr 26, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions pyccel/ast/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3821,6 +3821,64 @@ def __reduce_ex__(self, i):
mod_name = self.mod_name)
return (apply, (self.__class__, (), kwargs))


class TaskFunctionCall(FunctionCall):
pass

class Task(Basic):
Comment on lines +3825 to +3828
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these be in ast/omp.py ?

"""
"""
__slots__ = ('_stmt','_inputs','_outputs','_preceders', '_shareds', '_should_wait')
_attribute_nodes = ('_stmt','_inputs','_preceders')

def __init__(self, stmt, inputs = (), outputs = dict(), shareds = set(), preceders = ()):
self._stmt = stmt
self._inputs = inputs
self._outputs = outputs
self._preceders = preceders
self._shareds = shareds
self._should_wait = False
super().__init__()

@property
def stmt(self):
return self._stmt

@property
def inputs(self):
return self._inputs

@property
def outputs(self):
return self._outputs

@property
def preceders(self):
return self._preceders

@property
def shareds(self):
return self._shareds

@property
def should_wait(self):
return self._should_wait

@should_wait.setter
def should_wait(self, value):
self._should_wait = value

class TaskMaster(Task):
__slots__ = ('_num_threads',)

def __init__(self, num_threads, *args, **kwargs):
self._num_threads = num_threads
super().__init__(*args, **kwargs)

@property
def num_threads(self):
return self._num_threads

#==============================================================================
def process_shape(shape):
if not hasattr(shape,'__iter__'):
Expand Down
6 changes: 5 additions & 1 deletion pyccel/ast/sympy_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import sympy as sp
from sympy.core.numbers import One, NegativeOne, Zero, Half

from .operators import PyccelAdd, PyccelMul, PyccelPow, PyccelUnarySub
from .operators import PyccelAdd, PyccelMul, PyccelPow, PyccelUnarySub, PyccelFloorDiv
from .operators import PyccelDiv, PyccelMinus, PyccelAssociativeParenthesis
from .core import create_incremented_string

Expand Down Expand Up @@ -169,6 +169,10 @@ def pyccel_to_sympy(expr, symbol_map, used_names):
elif isinstance(expr, MathCeil):
return sp.ceiling(pyccel_to_sympy(expr.args[0], symbol_map, used_names))

elif isinstance(expr, PyccelFloorDiv):
args = [pyccel_to_sympy(e, symbol_map, used_names) for e in expr.args]
return args[0] // args[1]

elif expr in symbol_map.values():
return list(symbol_map.keys())[list(symbol_map.values()).index(expr)]

Expand Down
5 changes: 4 additions & 1 deletion pyccel/codegen/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,10 @@ def handle_error(stage):
lib_dest_path = os.path.join(pyccel_dirpath, lib_name)
with FileLock(lib_dest_path + '.lock'):
if not os.path.exists(lib_dest_path):
shutil.copytree(lib_path, lib_dest_path)
try:
shutil.copytree(lib_path, lib_dest_path)
except:
print('[Warning] : can\'t copy file permissions')

# stop after copying lib to __pyccel__ directory for
# convert only
Expand Down
27 changes: 27 additions & 0 deletions pyccel/codegen/printing/ccode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1600,9 +1600,36 @@ def _print_CommentBlock(self, expr):
def _print_EmptyNode(self, expr):
return ''

def _print_Task(self, expr):
inouts = []
inputs = expr.inputs

# resolve duplicated variables
outputs = [a if a not in inputs else inouts.append(a) for a in expr.outputs.keys()] if expr.outputs.keys() else None
inputs = [a for a in inputs if a not in inouts] if inputs else None

#printing
outputs = 'out:{}'.format(','.join(self._print(a) for a in outputs)) if outputs else ''
inputs = 'in:{}'.format(','.join(self._print(a) for a in inputs)) if inputs else ''
inouts = 'inout:{}'.format(','.join(self._print(a) for a in inouts)) if inouts else ''

depend = 'depend {}'.format(outputs + inputs + inouts) if inputs or outputs or inouts else ''

should_wait = '#pragma omp taskwait' if expr.should_wait else ''

start_task = '#pragma omp task {}'.format(depend) + '{\n'
structured_code_block = self._print(expr.stmt)
end_task = "}\n"

code = should_wait + start_task + structured_code_block + end_task
return code



#=================== OMP ==================

def _print_OmpAnnotatedComment(self, expr):
print(expr)
clauses = ''
if expr.combined:
clauses = ' ' + expr.combined
Expand Down
50 changes: 50 additions & 0 deletions pyccel/codegen/printing/fcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1851,6 +1851,56 @@ def _do_range(target, iterable, prolog, epilog):
'{body}'
'{epilog}').format(prolog=prolog, body=body, epilog=epilog)

def _print_Task(self, expr):

inputs = expr.inputs
outputs = tuple(i for i, v in expr.outputs.items() if v is True)
shareds = expr.shareds

inputs = ' depend(in:{})'.format(','.join(a.name for a in inputs)) if inputs else ''
outputs = ' depend(out:{})'.format(','.join(a.name for a in outputs)) if outputs else ''
shareds = ' shared({})'.format(', '.join(a.name for a in shareds)) if shareds else ''

code = ('!$omp task{shareds}{inputs}{outputs}\n'
'{statement}'
'!$omp end task\n'
'{should_wait}\n').format(shareds = shareds,
inputs = inputs,
outputs = outputs,
statement = self._print(expr.stmt),
should_wait = '!$omp taskwait' if expr.should_wait else '')
return code

def _print_TaskMaster(self, expr):
threads_num = ' num_threads({})'.format(self._print(expr.num_threads.python_value)) if expr.num_threads else ''

code = ('!$omp parallel{threads_num}\n'
'!$omp single\n'
'{statement}'
'!$omp end single\n'
'!$omp end parallel\n').format(threads_num = threads_num, statement = self._print(expr.stmt))

return code
# resolve duplicated variables
#outputs = [a if a not in inputs else inouts.append(a) for a in expr.outputs.keys()] if expr.outputs.keys() else None
#inputs = [a for a in inputs if a not in inouts] if inputs else None

#printing
#outputs = 'out:{}'.format(','.join(self._print(a) for a in outputs)) if outputs else ''
#inputs = 'in:{}'.format(','.join(self._print(a) for a in inputs)) if inputs else ''
#inouts = 'inout:{}'.format(','.join(self._print(a) for a in inouts)) if inouts else ''

#depend = 'depend {}'.format(outputs + inputs + inouts) if inputs or outputs or inouts else ''
#should_wait = '!$omp taskwait\n' if expr.should_wait else ''

#start_task = "!$omp task {}\n".format(depend)
#structured_code_block = self._print(expr.stmt)
#end_task = "!$omp end task\n"


#code = '{}'.format(start_task + structured_code_block + end_task + should_wait)
#return code

# .....................................................
# Print OpenMP AnnotatedComment
# .....................................................
Expand Down
20 changes: 19 additions & 1 deletion pyccel/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
'private',
'elemental',
'stack_array',
'allow_negative_index'
'allow_negative_index',
'task'
)

def lambdify(f):
Expand Down Expand Up @@ -96,3 +97,20 @@ def allow_negative_index(f,*args):
def identity(f):
return f
return identity


def task(type = 'child', threads_num = None):
"""
Decorator indicate that the function can be used in multithreading

Prameters
---------
type : string
indecate that the current function is responsible of running other
task functions ('master') or a task function ('child' / None)
threads_num : integer
number of threads reserved for this parallel region
"""
def identity(f):
return f
return identity
7 changes: 7 additions & 0 deletions pyccel/parser/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ def __init__(self, *, headers=None, decorators=None, templates=None):
self._symbolic_functions = OrderedDict()
self._python_functions = OrderedDict()

self._tasks = []

self._is_loop = False
# scoping for loops
self._loops = []
Expand Down Expand Up @@ -246,6 +248,11 @@ def is_loop(self):
def loops(self):
return self._loops

@property
def tasks(self):
"""
"""
return self._tasks



Expand Down
Loading