mirror of
https://gitlab.com/scemama/irpf90.git
synced 2025-01-03 01:55:42 +01:00
Add ashe and // support
This commit is contained in:
parent
f1ce16195f
commit
598587bcf3
2602
src/ashes.py
Normal file
2602
src/ashes.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,7 @@ options['p'] = [ 'preprocess' , 'Prints a preprocessed file to standard output
|
|||||||
options['r'] = [ 'no_directives', 'Ignore all compiler directives !DEC$ and !DIR$', 0 ]
|
options['r'] = [ 'no_directives', 'Ignore all compiler directives !DEC$ and !DIR$', 0 ]
|
||||||
options['s'] = [ 'substitute' , 'Substitute values in do loops for generating specific optimized code.', 1 ]
|
options['s'] = [ 'substitute' , 'Substitute values in do loops for generating specific optimized code.', 1 ]
|
||||||
options['t'] = [ 'touch' , 'Display which entities are touched when touching the variable given as an argument.', 1 ]
|
options['t'] = [ 'touch' , 'Display which entities are touched when touching the variable given as an argument.', 1 ]
|
||||||
|
options['T'] = [ 'Task' , 'Auto-parallelism ', 0 ]
|
||||||
options['v'] = [ 'version' , 'Prints version of irpf90', 0 ]
|
options['v'] = [ 'version' , 'Prints version of irpf90', 0 ]
|
||||||
options['w'] = [ 'warnings' , 'Activate Warnings', 0 ]
|
options['w'] = [ 'warnings' , 'Activate Warnings', 0 ]
|
||||||
options['z'] = [ 'openmp' , 'Activate for OpenMP code', 0 ]
|
options['z'] = [ 'openmp' , 'Activate for OpenMP code', 0 ]
|
||||||
|
264
src/entity.py
264
src/entity.py
@ -501,20 +501,157 @@ class Entity(object):
|
|||||||
if not self.is_main:
|
if not self.is_main:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
from ashes import AshesEnv
|
||||||
|
template = '''
|
||||||
|
{#l_allocate}
|
||||||
|
{subroutine|s}
|
||||||
|
{/l_allocate}
|
||||||
|
|
||||||
|
{?inline}
|
||||||
|
!DEC$ ATTRIBUTES FORCEINLINE :: provide_{name}
|
||||||
|
{/inline}
|
||||||
|
subroutine provide_{name}
|
||||||
|
|
||||||
|
{?do_openmp}
|
||||||
|
use omp_lib
|
||||||
|
{/do_openmp}
|
||||||
|
|
||||||
|
{#l_module}
|
||||||
|
{name}
|
||||||
|
{/l_module}
|
||||||
|
|
||||||
|
implicit none
|
||||||
|
character*(8+{@size key=name/}),parameter :: irp_here = 'provide_{name}'
|
||||||
|
|
||||||
|
{?do_openmp}
|
||||||
|
call irp_lock_{name}(.True.)
|
||||||
|
{/do_openmp}
|
||||||
|
|
||||||
|
{?do_debug}
|
||||||
|
call irp_enter(irp_here)
|
||||||
|
{/do_debug}
|
||||||
|
|
||||||
|
{#l_children}
|
||||||
|
if (.NOT.{name}_is_built) then
|
||||||
|
call provide_{name}
|
||||||
|
endif
|
||||||
|
{/l_children}
|
||||||
|
|
||||||
|
{#do_task}
|
||||||
|
!$omp task default(shared) {depend}
|
||||||
|
{/do_task}
|
||||||
|
|
||||||
|
{#l_allocate}
|
||||||
|
call allocate_{name}
|
||||||
|
{/l_allocate}
|
||||||
|
call bld_{name}
|
||||||
|
|
||||||
|
{#do_task}
|
||||||
|
!$omp end task
|
||||||
|
{/do_task}
|
||||||
|
|
||||||
|
{name}_is_built = .TRUE.
|
||||||
|
|
||||||
|
{?do_openmp}
|
||||||
|
call irp_lock_{name}(.False.)
|
||||||
|
{/do_openmp}
|
||||||
|
|
||||||
|
{?do_debug}
|
||||||
|
call irp_leave(irp_here)
|
||||||
|
{/do_debug}
|
||||||
|
|
||||||
|
end subroutine provide_{name}
|
||||||
|
'''
|
||||||
|
from util import mangled
|
||||||
|
|
||||||
name = self.name
|
name = self.name
|
||||||
same_as = self.same_as
|
var = self.d_entity[name]
|
||||||
|
l_module = [ {'name':x} for x in build_use([self.name] + self.to_provide, self.d_entity)]
|
||||||
|
l_allocate = [ {'name':n, 'subroutine':self.build_alloc(n)} for n in self.l_name if self.d_entity[n].dim]
|
||||||
|
l_children = [ {'name':x} for x in mangled(self.to_provide, self.d_entity) ]
|
||||||
|
|
||||||
|
in_ = ['depend(in: %s)' % n for n in self.to_provide]
|
||||||
|
out_ = ['depend(out: %s)' % n for n in self.l_name]
|
||||||
|
do_task = [ {'depend':' '.join(in_ + out_) } ] if command_line.do_Task else []
|
||||||
|
|
||||||
|
ashes_env = AshesEnv()
|
||||||
|
ashes_env.register_source('provide',template)
|
||||||
|
|
||||||
|
l = ashes_env.render('provide', {'name': name,
|
||||||
|
'l_module':l_module,
|
||||||
|
'l_allocate':l_allocate,
|
||||||
|
'l_children':l_children,
|
||||||
|
'do_debug':command_line.do_debug,
|
||||||
|
'do_openmp':command_line.do_openmp,
|
||||||
|
'do_task':do_task})
|
||||||
|
|
||||||
|
return l.split('\n')
|
||||||
|
|
||||||
|
def build_alloc(self,name):
|
||||||
|
var = self.d_entity[name]
|
||||||
|
from ashes import AshesEnv
|
||||||
|
template = ("""
|
||||||
|
|
||||||
|
subroutine allocate_{name}
|
||||||
|
|
||||||
|
{#l_module}
|
||||||
|
{name}
|
||||||
|
{/l_module}
|
||||||
|
|
||||||
|
character*(9+{@size key=name/}),parameter :: irp_here = 'allocate_{name}'
|
||||||
|
integer :: irp_err
|
||||||
|
|
||||||
|
if ( allocated({name}) .AND.( &
|
||||||
|
{#l_dim}
|
||||||
|
( SIZE({name},{rank}) /= {value} ) {@sep}.OR.{/sep} &
|
||||||
|
{/l_dim}
|
||||||
|
)) then
|
||||||
|
|
||||||
|
{?do_memory}
|
||||||
|
print *, irp_here//': Deallocated {name}'
|
||||||
|
{/do_memory}
|
||||||
|
|
||||||
|
deallocate( {name}, stat=irp_err )
|
||||||
|
|
||||||
|
if (irp_err /= 0) then
|
||||||
|
print *, irp_here//': Deallocation failed: {name}'
|
||||||
|
print *,' size: {dim}'
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ( .NOT. allocated({name}) ) then
|
||||||
|
|
||||||
|
{?do_memory}
|
||||||
|
print *, irp_here//': Allocate {name} ({dim})'
|
||||||
|
{/do_memory}
|
||||||
|
|
||||||
|
{^corray}
|
||||||
|
allocate({name} ({dim}), stat=irp_err)
|
||||||
|
{:else}
|
||||||
|
allocate({name} ({dim}[*]), stat=irp_err)
|
||||||
|
{/corray}
|
||||||
|
if (irp_err /= 0) then
|
||||||
|
print *, irp_here//': Allocation failed: {name}'
|
||||||
|
print *,' size: {dim}'
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
end subroutine
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
def dimsize(x):
|
def dimsize(x):
|
||||||
# (str) -> str
|
# (str) -> str
|
||||||
'''Compute the number of element in the array'''
|
'''Compute the number of element in the array'''
|
||||||
try:
|
try:
|
||||||
b0, b1 = x.split(':')
|
b0, b1 = x.split(':')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return x
|
return x
|
||||||
|
|
||||||
b0_is_digit = b0.replace('-', '').isdigit()
|
b0_is_digit = b0.replace('-', '').isdigit()
|
||||||
b1_is_digit = b1.replace('-', '').isdigit()
|
b1_is_digit = b1.replace('-', '').isdigit()
|
||||||
|
|
||||||
|
|
||||||
if b0_is_digit and b1_is_digit:
|
if b0_is_digit and b1_is_digit:
|
||||||
size = str(int(b1) - int(b0) + 1)
|
size = str(int(b1) - int(b0) + 1)
|
||||||
@ -524,105 +661,20 @@ class Entity(object):
|
|||||||
size = "(%d) - (%s)" % (int(b1) + 1, b0)
|
size = "(%d) - (%s)" % (int(b1) + 1, b0)
|
||||||
else:
|
else:
|
||||||
size = "(%s) - (%s) + 1" % (b1, b0)
|
size = "(%s) - (%s) + 1" % (b1, b0)
|
||||||
|
|
||||||
return size
|
return size
|
||||||
|
|
||||||
def build_alloc(name):
|
l_dim = [{'name':name, 'rank':i+1, 'value':dimsize(k)} for i, k in enumerate(var.dim)]
|
||||||
|
l_module = [ {'name':x} for x in build_use([var.name] + var.needs, self.d_entity) ]
|
||||||
|
|
||||||
var = self.d_entity[name]
|
ashes_env = AshesEnv()
|
||||||
if var.dim == []:
|
ashes_env.register_source('hello',template)
|
||||||
return []
|
|
||||||
|
return ashes_env.render('hello', {'name': name,
|
||||||
from util import build_dim
|
'dim':','.join(var.dim),
|
||||||
|
'corray': command_line.coarray,
|
||||||
def print_size():
|
'l_dim': l_dim,
|
||||||
return " " * 5 + "print *, ' size: {0}'".format(build_dim(var.dim))
|
'l_module':l_module,
|
||||||
|
'do_memory':command_line.do_memory})
|
||||||
def check_dimensions():
|
|
||||||
l = ["(%s>0)" % dimsize(x) for x in var.dim]
|
|
||||||
str_ = ".and.".join(l)
|
|
||||||
return " if (%s) then" % (str_)
|
|
||||||
|
|
||||||
def dimensions_OK():
|
|
||||||
result = [" irp_dimensions_OK = .True."]
|
|
||||||
for i, k in enumerate(var.dim):
|
|
||||||
result.append(" irp_dimensions_OK = irp_dimensions_OK.AND.(SIZE(%s,%d)==(%s))"
|
|
||||||
% (name, i + 1, dimsize(k)))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def do_allocate():
|
|
||||||
if command_line.coarray:
|
|
||||||
result = " allocate(%s(%s)[*],stat=irp_err)"
|
|
||||||
else:
|
|
||||||
result = " allocate(%s(%s),stat=irp_err)"
|
|
||||||
result = result % (name, ','.join(var.dim))
|
|
||||||
if command_line.do_memory:
|
|
||||||
tmp = "\n print *, %s, 'Allocating %s(%s)'"
|
|
||||||
d = ','.join(self.dim)
|
|
||||||
result += tmp % ('size(' + name + ')', name, d)
|
|
||||||
return result
|
|
||||||
|
|
||||||
result = [" if (allocated (%s) ) then" % (name)]
|
|
||||||
result += dimensions_OK()
|
|
||||||
result += [
|
|
||||||
" if (.not.irp_dimensions_OK) then", " deallocate(%s,stat=irp_err)" % (name),
|
|
||||||
" if (irp_err /= 0) then", " print *, irp_here//': Deallocation failed: %s'" %
|
|
||||||
(name), print_size(), " endif"
|
|
||||||
]
|
|
||||||
|
|
||||||
if command_line.do_memory:
|
|
||||||
result += [" print *, 'Deallocating %s'" % (name)]
|
|
||||||
result.append(check_dimensions())
|
|
||||||
result.append(do_allocate())
|
|
||||||
result += [\
|
|
||||||
" if (irp_err /= 0) then",
|
|
||||||
" print *, irp_here//': Allocation failed: %s'"%(name),
|
|
||||||
print_size(),
|
|
||||||
" endif",
|
|
||||||
" endif",
|
|
||||||
" endif",
|
|
||||||
" else" ]
|
|
||||||
result.append(check_dimensions())
|
|
||||||
result.append(do_allocate())
|
|
||||||
result += [
|
|
||||||
" if (irp_err /= 0) then", " print *, irp_here//': Allocation failed: %s'" %
|
|
||||||
(name), print_size(), " endif", " endif", " endif"
|
|
||||||
]
|
|
||||||
return result
|
|
||||||
|
|
||||||
result = []
|
|
||||||
if command_line.directives and command_line.inline in ["all", "providers"]:
|
|
||||||
result += ["!DEC$ ATTRIBUTES FORCEINLINE :: provide_%s" % (name)]
|
|
||||||
result += ["subroutine provide_%s" % (name)]
|
|
||||||
result += build_use([same_as] + self.to_provide, self.d_entity)
|
|
||||||
if command_line.do_openmp:
|
|
||||||
result += [" use omp_lib"]
|
|
||||||
result.append(" implicit none")
|
|
||||||
length = len("provide_%s" % (name))
|
|
||||||
result += [
|
|
||||||
" character*(%d) :: irp_here = 'provide_%s'" % (length, name),
|
|
||||||
" integer :: irp_err ",
|
|
||||||
" logical :: irp_dimensions_OK",
|
|
||||||
"!$ integer :: nthreads"
|
|
||||||
]
|
|
||||||
if command_line.do_openmp:
|
|
||||||
result.append(" call irp_lock_%s(.True.)" % (same_as))
|
|
||||||
if command_line.do_assert or command_line.do_debug:
|
|
||||||
result.append(" call irp_enter(irp_here)")
|
|
||||||
result += build_call_provide(self.to_provide, self.d_entity)
|
|
||||||
result += flatten(map(build_alloc, self.l_name))
|
|
||||||
result += [
|
|
||||||
" if (.not.%s_is_built) then" % (same_as), " call bld_%s" % (same_as),
|
|
||||||
" %s_is_built = .True." % (same_as), ""
|
|
||||||
]
|
|
||||||
result += [" endif"]
|
|
||||||
if command_line.do_assert or command_line.do_debug:
|
|
||||||
result.append(" call irp_leave(irp_here)")
|
|
||||||
if command_line.do_openmp:
|
|
||||||
result.append(" call irp_lock_%s(.False.)" % (same_as))
|
|
||||||
result.append("end subroutine provide_%s" % (name))
|
|
||||||
result.append("")
|
|
||||||
return result
|
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
@irpy.lazy_property
|
@irpy.lazy_property
|
||||||
|
@ -667,6 +667,11 @@ def irp_simple_statements(text):
|
|||||||
assert type(line) == Program
|
assert type(line) == Program
|
||||||
program_name = line.lower.split()[1]
|
program_name = line.lower.split()[1]
|
||||||
temp = [Program(0, "program irp_program", program_name)]
|
temp = [Program(0, "program irp_program", program_name)]
|
||||||
|
|
||||||
|
if command_line.do_Task:
|
||||||
|
for i in [" call omp_set_nested(.TRUE.)", "!$omp parallel", "!$omp single"]:
|
||||||
|
temp += [Simple_line(0, i, line.filename)]
|
||||||
|
|
||||||
if command_line.do_profile:
|
if command_line.do_profile:
|
||||||
temp += [Simple_line(0, "call irp_init_timer()", line.filename)]
|
temp += [Simple_line(0, "call irp_init_timer()", line.filename)]
|
||||||
if command_line.do_openmp:
|
if command_line.do_openmp:
|
||||||
@ -676,10 +681,16 @@ def irp_simple_statements(text):
|
|||||||
temp += [Simple_line(0, "call irp_print_timer()", line.filename)]
|
temp += [Simple_line(0, "call irp_print_timer()", line.filename)]
|
||||||
|
|
||||||
temp += [Simple_line(0, " call irp_finalize_%s()" % (irp_id), line.filename)]
|
temp += [Simple_line(0, " call irp_finalize_%s()" % (irp_id), line.filename)]
|
||||||
|
|
||||||
|
if command_line.do_Task:
|
||||||
|
for i in ["!$omp taskwait","!$omp end single", "!$omp end parallel"]:
|
||||||
|
temp += [Simple_line(0, i, line.filename)]
|
||||||
|
|
||||||
temp += [End(0, "end program", line.filename)]
|
temp += [End(0, "end program", line.filename)]
|
||||||
|
|
||||||
result = temp + process_subroutine(
|
result = temp + process_subroutine(
|
||||||
Subroutine(line.i, "subroutine %s" % (program_name, ), line.filename))
|
Subroutine(line.i, "subroutine %s" % (program_name, ), line.filename))
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
d = {
|
d = {
|
||||||
|
Loading…
Reference in New Issue
Block a user