From a12d57700787657659c543962b4ec9211115a07f Mon Sep 17 00:00:00 2001 From: Keck Jean-Baptiste <jean-baptiste.keck@imag.fr> Date: Tue, 6 Jun 2017 21:36:21 +0200 Subject: [PATCH] fixed topologies --- .../device/codegen/functions/advection_rhs.py | 14 +++--- .../device/codegen/functions/apply_stencil.py | 8 ++-- .../device/codegen/functions/cache_load.py | 8 ++-- .../device/codegen/functions/compute_index.py | 2 +- .../codegen/functions/stretching_rhs.py | 16 +++---- .../codegen/kernels/directional_advection.py | 45 +++++++------------ .../codegen/kernels/directional_stretching.py | 14 +++--- .../tests/test_directional_advection.py | 25 +++++++---- .../tests/test_directional_stretching.py | 14 +++--- .../device/opencl/opencl_array_backend.py | 18 ++++++-- .../operator/directional/advection_dir.py | 18 +++++--- .../host/fortran/operator/diffusion.py | 8 +++- .../host/fortran/operator/fortran_fftw.py | 20 +++++---- .../backend/host/fortran/operator/poisson.py | 14 +++--- hysop/backend/host/host_allocator.py | 3 +- hysop/backend/host/host_array_backend.py | 2 +- hysop/core/arrays/array_backend.py | 14 ++++++ hysop/core/graph/computational_graph.py | 11 ++++- hysop/core/graph/computational_node.py | 31 +++++++++++-- hysop/core/graph/computational_operator.py | 14 ++++++ hysop/core/memory/mempool.py | 2 +- hysop/core/mpi/redistribute.py | 1 + hysop/core/mpi/topology.py | 4 +- hysop/deps.py | 2 +- 24 files changed, 198 insertions(+), 110 deletions(-) diff --git a/hysop/backend/device/codegen/functions/advection_rhs.py b/hysop/backend/device/codegen/functions/advection_rhs.py index da083a708..23cc392a3 100644 --- a/hysop/backend/device/codegen/functions/advection_rhs.py +++ b/hysop/backend/device/codegen/functions/advection_rhs.py @@ -18,7 +18,7 @@ from hysop.numerics.stencil.stencil import Stencil class DirectionalAdvectionRhsFunction(OpenClFunctionCodeGenerator): def __init__(self, typegen, ftype, work_dim, nparticles, is_cached, boundary, - restrict=True, + ptr_restrict=True, itype='int', known_args=None): @@ -36,10 +36,10 @@ class DirectionalAdvectionRhsFunction(OpenClFunctionCodeGenerator): vtype = typegen.vtype(ftype,nparticles) (args,basename) = self.build_prototype(typegen,work_dim,itype,ftype,vtype, - nparticles,restrict,storage,is_cached, is_periodic) + nparticles,ptr_restrict,storage,is_cached, is_periodic) reqs = self.build_requirements(typegen,work_dim,itype,ftype,vtype, - nparticles,restrict,storage,is_cached, is_periodic) + nparticles,ptr_restrict,storage,is_cached, is_periodic) super(DirectionalAdvectionRhsFunction,self).__init__(basename=basename, output=vtype,typegen=typegen,inline=True, @@ -61,19 +61,19 @@ class DirectionalAdvectionRhsFunction(OpenClFunctionCodeGenerator): self.gencode() def build_prototype(self,typegen,work_dim,itype,ftype,vtype, - nparticles,restrict,storage,is_cached, is_periodic): + nparticles,ptr_restrict,storage,is_cached, is_periodic): args = ArgDict() args['line_velocity'] = CodegenVariable('line_velocity', ftype, typegen, const=True, add_impl_const=True, - storage=storage, ptr=True, restrict=restrict, nl=True) + storage=storage, ptr=True, ptr_restrict=ptr_restrict, nl=True) args['X'] = CodegenVectorClBuiltin('X', ftype, nparticles, typegen, add_impl_const=True, nl=True) if is_periodic and (not is_cached): args['line_width'] = CodegenVariable('line_width', itype, typegen, add_impl_const=True) args['line_offset'] = CodegenVariable('line_offset', itype, typegen, add_impl_const=True,nl=True) - args['rk_step'] = CodegenVariable('rk_step', itype, typegen, add_impl_const=True) + args['rk_step'] = CodegenVariable('rk_step', itype, typegen) args['inv_dx'] = CodegenVariable('inv_dx', ftype, typegen, add_impl_const=True, nl=True) # args['active'] = CodegenVariable('active','bool',typegen, add_impl_const=True) @@ -83,7 +83,7 @@ class DirectionalAdvectionRhsFunction(OpenClFunctionCodeGenerator): return (args,basename) def build_requirements(self,typegen,work_dim,itype,ftype,vtype, - nparticles,restrict,storage,is_cached, is_periodic): + nparticles,ptr_restrict,storage,is_cached, is_periodic): reqs = WriteOnceDict() return reqs diff --git a/hysop/backend/device/codegen/functions/apply_stencil.py b/hysop/backend/device/codegen/functions/apply_stencil.py index 682e7c269..1fdd04e1f 100644 --- a/hysop/backend/device/codegen/functions/apply_stencil.py +++ b/hysop/backend/device/codegen/functions/apply_stencil.py @@ -21,7 +21,7 @@ class ApplyStencilFunction(OpenClFunctionCodeGenerator): op='{vinput0}[id]', custom_id=None, vector_suffixes=None, - data_storage='__local', restrict=True, + data_storage='__local', ptr_restrict=True, multipliers={}, itype='int', known_args=None): @@ -48,17 +48,17 @@ class ApplyStencilFunction(OpenClFunctionCodeGenerator): if vectorize: name = iname args[name] = CodegenVariable(name, vtype, typegen, const=True, - add_impl_const=True, storage=data_storage, ptr=True, restrict=restrict) + add_impl_const=True, storage=data_storage, ptr=True, ptr_restrict=ptr_restrict) else: for i in xrange(components): name = '{}{}'.format(iname,vector_suffixes[i]) args[name] = CodegenVariable(name, ftype, typegen, const=True, add_impl_const=True, storage=data_storage, - ptr=True, restrict=restrict) + ptr=True, ptr_restrict=ptr_restrict) for iname in scalar_inputs: name = iname args[name] = CodegenVariable(name, ftype, typegen, const=True, - add_impl_const=True, storage=data_storage, ptr=True, restrict=restrict) + add_impl_const=True, storage=data_storage, ptr=True, ptr_restrict=ptr_restrict) for arg in extra_inputs: args[arg.name] = arg diff --git a/hysop/backend/device/codegen/functions/cache_load.py b/hysop/backend/device/codegen/functions/cache_load.py index 29782fa47..852d8eb28 100644 --- a/hysop/backend/device/codegen/functions/cache_load.py +++ b/hysop/backend/device/codegen/functions/cache_load.py @@ -48,20 +48,20 @@ class CacheLoadFunction(OpenClFunctionCodeGenerator): args = ArgDict() if src_vectorize: args['src'] = CodegenVariable('src', vtype, typegen=tg, ptr=True, const=True, - storage='__global', nl=True, restrict=True) + storage='__global', nl=True, ptr_restrict=True) else: for i in xrange(components): src = 'src{}'.format(i) args[src] = CodegenVariable(src, ftype, typegen=tg, ptr=True, const=True, - storage='__global', nl=True, restrict=True) + storage='__global', nl=True, ptr_restrict=True) if dst_vectorize: args['dst'] = CodegenVariable('dst', vtype, typegen=tg, ptr=True, const=False, - storage='__local' , nl=True, restrict=True) + storage='__local' , nl=True, ptr_restrict=True) else: for i in xrange(components): dst = 'dst{}'.format(i) args[dst] = CodegenVariable(dst, ftype, typegen=tg, ptr=True, const=False, - storage='__local' , nl=True, restrict=True) + storage='__local' , nl=True, ptr_restrict=True) args['global_id'] = CodegenVectorClBuiltin('gid',itype,work_dim,typegen, add_impl_const=False) diff --git a/hysop/backend/device/codegen/functions/compute_index.py b/hysop/backend/device/codegen/functions/compute_index.py index 2a92a6c30..2208ac321 100644 --- a/hysop/backend/device/codegen/functions/compute_index.py +++ b/hysop/backend/device/codegen/functions/compute_index.py @@ -12,7 +12,7 @@ class ComputeIndexFunction(OpenClFunctionCodeGenerator): def __init__(self,typegen,dim,wrap=None,itype='int'): assert dim>0 args = ArgDict() - args['idx'] = CodegenVectorClBuiltin('idx', 'int', dim, typegen, add_impl_const=(wrap==False)) + args['idx'] = CodegenVectorClBuiltin('idx', 'int', dim, typegen, add_impl_const=bool(wrap==False)) args['size'] = CodegenVectorClBuiltin('size', itype, dim, typegen, add_impl_const=True) args['wrap'] = CodegenVariable('wrap', 'bool',typegen, add_impl_const=True, value=wrap) diff --git a/hysop/backend/device/codegen/functions/stretching_rhs.py b/hysop/backend/device/codegen/functions/stretching_rhs.py index fcb9f2bcb..5cda6360b 100644 --- a/hysop/backend/device/codegen/functions/stretching_rhs.py +++ b/hysop/backend/device/codegen/functions/stretching_rhs.py @@ -27,7 +27,7 @@ class DirectionalStretchingRhsFunction(OpenClFunctionCodeGenerator): } def __init__(self, typegen, dim, ftype, order, direction, formulation, cached, boundary, - restrict=True, vectorize_u=False, + ptr_restrict=True, vectorize_u=False, itype='int', used_variables = _default_used_variables, known_args=None): @@ -50,11 +50,11 @@ class DirectionalStretchingRhsFunction(OpenClFunctionCodeGenerator): vtype = typegen.vtype(ftype,dim) (args,basename) = self.build_prototype(typegen,dim,itype,ftype,vtype,order, - direction,cached,restrict,storage,vectorize_u,used_variables, + direction,cached,ptr_restrict,storage,vectorize_u,used_variables, formulation,is_conservative,is_periodic) reqs = self.build_requirements(typegen,dim,itype,ftype,vtype,order,direction, - boundary,cached,restrict,storage,vectorize_u,used_variables, + boundary,cached,ptr_restrict,storage,vectorize_u,used_variables, is_conservative,is_periodic,args) super(DirectionalStretchingRhsFunction,self).__init__(basename=basename, @@ -82,7 +82,7 @@ class DirectionalStretchingRhsFunction(OpenClFunctionCodeGenerator): self.gencode() def build_prototype(self,typegen,dim,itype,ftype,vtype,order,direction,cached, - restrict,storage, vectorize_u,used_variables,formulation,is_conservative,is_periodic): + ptr_restrict,storage, vectorize_u,used_variables,formulation,is_conservative,is_periodic): U = used_variables['U'] W = used_variables['W'] @@ -91,14 +91,14 @@ class DirectionalStretchingRhsFunction(OpenClFunctionCodeGenerator): args = ArgDict() if vectorize_u: - args[U] = CodegenVariable(U, vtype, typegen, const=True, add_impl_const=True, storage=storage, ptr=True, restrict=restrict,nl=True) + args[U] = CodegenVariable(U, vtype, typegen, const=True, add_impl_const=True, storage=storage, ptr=True, ptr_restrict=ptr_restrict,nl=True) else: for i in xrange(dim): Uxyz= '{}{}'.format(U,xyz[i]) - args[Uxyz] = CodegenVariable(Uxyz, ftype, typegen, const=True, add_impl_const=True, storage=storage, ptr=True, restrict=restrict, nl=True) + args[Uxyz] = CodegenVariable(Uxyz, ftype, typegen, const=True, add_impl_const=True, storage=storage, ptr=True, ptr_restrict=ptr_restrict, nl=True) if is_conservative: Wd= '{}{}'.format(W,xyz[direction]) - args[Wd] = CodegenVariable(Wd, ftype, typegen, const=False, add_impl_const=True, storage=storage, ptr=True, restrict=restrict, nl=True) + args[Wd] = CodegenVariable(Wd, ftype, typegen, const=False, add_impl_const=True, storage=storage, ptr=True, ptr_restrict=ptr_restrict, nl=True) args[W] = CodegenVectorClBuiltin(W, ftype, dim, typegen, add_impl_const=True) args['inv_dx'] = CodegenVariable('inv_dx', ftype, typegen, add_impl_const=True, nl=True) @@ -130,7 +130,7 @@ class DirectionalStretchingRhsFunction(OpenClFunctionCodeGenerator): return stencil def build_requirements(self, typegen,dim,itype,ftype,vtype,order,direction,boundary,cached, - restrict,storage,vectorize_u,used_variables,is_conservative,is_periodic,args): + ptr_restrict,storage,vectorize_u,used_variables,is_conservative,is_periodic,args): reqs = WriteOnceDict() diff --git a/hysop/backend/device/codegen/kernels/directional_advection.py b/hysop/backend/device/codegen/kernels/directional_advection.py index d22ec82ba..283ad06fc 100644 --- a/hysop/backend/device/codegen/kernels/directional_advection.py +++ b/hysop/backend/device/codegen/kernels/directional_advection.py @@ -230,7 +230,7 @@ class DirectionalAdvectionKernel(KernelCodeGenerator): advection_rhs = DirectionalAdvectionRhsFunction(typegen=typegen, work_dim=work_dim, ftype=ftype, is_cached=is_cached, boundary=vboundary[0], nparticles=nparticles, - restrict=True, + ptr_restrict=True, itype=itype) used_vars = RungeKuttaFunction._default_used_vars.copy() @@ -253,22 +253,22 @@ class DirectionalAdvectionKernel(KernelCodeGenerator): add_impl_const=True,nl=True) kargs['velocity_base'] = CodegenVariable(storage=self._global,name='velocity_base', - ctype=ftype, typegen=typegen, restrict=True,ptr=True,const=True, + ctype=ftype, typegen=typegen, ptr_restrict=True,ptr=True,const=True, add_impl_const=True, nl=False) kargs['velocity_offset'] = CodegenVariable(ctype='unsigned long',name='velocity_offset', typegen=typegen, add_impl_const=True,nl=True) kargs['position_base'] = CodegenVariable(storage=self._global,name='position_base', - ctype=ftype, typegen=typegen, restrict=True, ptr=True,const=False, + ctype=ftype, typegen=typegen, ptr_restrict=True, ptr=True,const=False, add_impl_const=True, nl=False) kargs['position_offset'] = CodegenVariable(ctype='unsigned long',name='position_offset', typegen=typegen,add_impl_const=True,nl=True) if debug_mode: kargs['dbg0'] = CodegenVariable(storage=self._global,name='dbg0',ctype=itype, - typegen=typegen, restrict=True,ptr=True,const=False,add_impl_const=True) + typegen=typegen, ptr_restrict=True,ptr=True,const=False,add_impl_const=True) kargs['dbg1'] = CodegenVariable(storage=self._global,name='dbg1',ctype=itype, - typegen=typegen, restrict=True,ptr=True,const=False,add_impl_const=True) + typegen=typegen, ptr_restrict=True,ptr=True,const=False,add_impl_const=True) kargs['velocity_mesh_info'] = requirements['MeshInfoStruct'].build_codegen_variable( const=True, name='velocity_mesh_info') @@ -277,7 +277,7 @@ class DirectionalAdvectionKernel(KernelCodeGenerator): if is_cached and not local_size_known: kargs['Vc'] = CodegenVariable(storage=_local,ctype=ftype, add_impl_const=True, - name='Vc', ptr=True, restrict=True, typegen=typegen, nl=False) + name='Vc', ptr=True, ptr_restrict=True, typegen=typegen, nl=False) return kargs @@ -321,10 +321,10 @@ class DirectionalAdvectionKernel(KernelCodeGenerator): position_offset = s.vars['position_offset'] velocity = CodegenVariable(storage=s._global,name='velocity', - ctype=ftype, typegen=tg, restrict=True, ptr=True, const=True, + ctype=ftype, typegen=tg, ptr_restrict=True, ptr=True, const=True, add_impl_const=True) position = CodegenVariable(storage=s._global,name='position', - ctype=ftype, typegen=tg, restrict=True, ptr=True, const=False) + ctype=ftype, typegen=tg, ptr_restrict=True, ptr=True, const=False) grid_size = position_mesh_info['local_mesh']['resolution'].view( 'grid_size', slice(None,work_dim)) @@ -347,7 +347,7 @@ class DirectionalAdvectionKernel(KernelCodeGenerator): line_index = CodegenVariable(name='line_index', ctype=itype, typegen=tg) line_offset = CodegenVariable(name='line_offset', ctype=itype, typegen=tg,const=True) line_velocity = CodegenVariable(name='line_velocity', ctype=ftype, ptr=True, - storage='__global', restrict=True, const=True, add_impl_const=True, typegen=tg) + storage='__global', ptr_restrict=True, const=True, add_impl_const=True, typegen=tg) X = CodegenVectorClBuiltin('X', ftype, nparticles, typegen=tg) pid = CodegenVectorClBuiltin('pid', itype, nparticles, typegen=tg, @@ -588,36 +588,25 @@ class DirectionalAdvectionKernel(KernelCodeGenerator): p_ghosts = position_mesh_info['ghosts'].value[:dim] p_dx = position_mesh_info['dx'].value[:dim] - vboundary = (v_lboundary[dir], v_rboundary[dir]) + vboundary = (v_lboundary[0], v_rboundary[0]) min_v_ghosts = int(math.ceil(cfl)) - min_p_ghosts = int(math.ceil(cfl*v_dx[direction]/p_dx[direction])) + min_p_ghosts = 0 assert (min_v_ghosts>=1) - assert (min_p_ghosts>=1) if not cl_env.is_multi_device: - if v_lboundary[dir] == BoundaryCondition.PERIODIC: - assert v_rboundary[dir] == BoundaryCondition.PERIODIC + if v_lboundary[0] == BoundaryCondition.PERIODIC: + assert v_rboundary[0] == BoundaryCondition.PERIODIC min_v_ghosts = 0 - if p_lboundary[dir] == BoundaryCondition.PERIODIC: - assert p_rboundary[dir] == BoundaryCondition.PERIODIC - min_p_ghosts = 0 - if (v_ghosts[dir] < min_v_ghosts): - msg= 'Given boundary condition implies minimum ghosts numbers to be at least {}' + if (v_ghosts[0] < min_v_ghosts): + msg= 'Given boundary condition implies minimum ghosts numbers to be at least {} ' msg+='in current direction for velocity but only {} ghosts ' msg+='are present in the grid.' - msg=msg.format(min_v_ghosts, v_ghosts[dir]) + msg=msg.format(min_v_ghosts, v_ghosts[0]) raise ValueError(msg) - if (p_ghosts[dir] < min_p_ghosts): - msg= 'Given boundary condition implies minimum ghosts numbers to be at least {}' - msg+='in current direction for position but only {} ghosts ' - msg+='are present in the grid.' - msg=msg.format(min_p_ghosts, p_ghosts[dir]) - raise ValueError(msg) - - is_multi_scale = (v_resolution[dir] != p_resolution[dir]) + is_multi_scale = (v_resolution[0] != p_resolution[0]) if is_multi_scale: msg='Compute_resolution mismatch between velocity and particles, ' msg+='got {} and {} and multiscale has not been implemented yet.' diff --git a/hysop/backend/device/codegen/kernels/directional_stretching.py b/hysop/backend/device/codegen/kernels/directional_stretching.py index 76b621a26..96363a696 100644 --- a/hysop/backend/device/codegen/kernels/directional_stretching.py +++ b/hysop/backend/device/codegen/kernels/directional_stretching.py @@ -261,7 +261,7 @@ class DirectionalStretchingKernel(KernelCodeGenerator): ftype=ftype, cached=is_cached, order=order, direction=direction, boundary=boundary, formulation=formulation, - restrict=True, vectorize_u=False, + ptr_restrict=True, vectorize_u=False, itype='int') used_vars = RungeKuttaFunction._default_used_vars.copy() @@ -292,17 +292,17 @@ class DirectionalStretchingKernel(KernelCodeGenerator): for i in xrange(work_dim): name = svelocity+xyz[i] kargs[name] = CodegenVariable(storage=_global,name=name,typegen=typegen, - ctype=ftype,ptr=True,restrict=True,const=True,add_impl_const=True) + ctype=ftype,ptr=True,ptr_restrict=True,const=True,add_impl_const=True) for i in xrange(work_dim): name = svorticity+xyz[i]+'_in' kargs[name] = CodegenVariable(storage=_global,name=name,typegen=typegen, - ctype=ftype,ptr=True,restrict=(not is_inplace),const=True,add_impl_const=True) + ctype=ftype,ptr=True,ptr_restrict=(not is_inplace),const=True,add_impl_const=True) for i in xrange(work_dim): name = svorticity+xyz[i]+'_out' kargs[name] = CodegenVariable(storage=_global,name=name,typegen=typegen, - ctype=ftype,ptr=True,restrict=(not is_inplace),const=False,add_impl_const=True) + ctype=ftype,ptr=True,ptr_restrict=(not is_inplace),const=False,add_impl_const=True) kargs['velocity_mesh_info'] = \ requirements['MeshInfoStruct'].build_codegen_variable(const=True, @@ -313,7 +313,7 @@ class DirectionalStretchingKernel(KernelCodeGenerator): if is_cached and not local_size_known: kargs['buffer'] = CodegenVariable(storage=_local,ctype=ftype, - add_impl_const=True, name='buffer', ptr=True, restrict=True, + add_impl_const=True, name='buffer', ptr=True, ptr_restrict=True, typegen=typegen, nl=False) self.svorticity = svorticity @@ -393,7 +393,7 @@ class DirectionalStretchingKernel(KernelCodeGenerator): buf = s.vars['buffer'] init = '{} + {}*{}'.format(buf(), i, local_size[0]) Vic = CodegenVariable(storage=storage,name=Vi+'c',ctype=ftype,typegen=tg, - const=True, restrict=True,ptr=True,init=init) + const=True, ptr_restrict=True,ptr=True,init=init) cached_vars[Vi] = Vic if is_conservative: @@ -405,7 +405,7 @@ class DirectionalStretchingKernel(KernelCodeGenerator): buf = s.vars['buffer'] init = '{} + {}*{}'.format(buf(), work_dim, local_size[0]) Wic = CodegenVariable(storage=storage,name=Wi+'c',ctype=ftype,typegen=tg, - const=True, restrict=True,ptr=True,init=init) + const=True, ptr_restrict=True,ptr=True,init=init) cached_vars[Wi] = Wic _U = self.svelocity diff --git a/hysop/backend/device/codegen/kernels/tests/test_directional_advection.py b/hysop/backend/device/codegen/kernels/tests/test_directional_advection.py index 0ef8ad42a..5c9d905df 100644 --- a/hysop/backend/device/codegen/kernels/tests/test_directional_advection.py +++ b/hysop/backend/device/codegen/kernels/tests/test_directional_advection.py @@ -22,7 +22,8 @@ class TestDirectionalAdvection(object): ctx = typegen.context grid_size = np.asarray([64,64,1]) - (A,grid_mesh_info) = _test_mesh_info(typegen,3,0,grid_size) + (A,grid_mesh_info) = _test_mesh_info('velocity_mesh_info',typegen,3,0,grid_size) + (_,position_mesh_info) = _test_mesh_info('position_mesh_info',typegen,3,0,grid_size) dx = A['dx'][0][0] inv_dx = A['inv_dx'][0][0] @@ -30,14 +31,14 @@ class TestDirectionalAdvection(object): umax = 1.0 min_ghosts = int(math.ceil(dt*umax/float(dx))) - ghosts = min_ghosts + 0 + ghosts = min_ghosts print 'min ghosts are: {}'.format(min_ghosts) print 'actual ghosts are: {}'.format(ghosts) compute_grid_ghosts = np.asarray([ghosts,0,0]) compute_grid_size = grid_size + 2*compute_grid_ghosts - (B,compute_grid_mesh_info) = _test_mesh_info(typegen,3,compute_grid_ghosts,compute_grid_size) + (B,compute_grid_mesh_info) = _test_mesh_info('velocity_mesh_info',typegen,3,compute_grid_ghosts,compute_grid_size) grid_shape = grid_size[::-1] compute_grid_shape = compute_grid_size[::-1] @@ -101,6 +102,7 @@ class TestDirectionalAdvection(object): cls.grid_mesh_info = grid_mesh_info cls.compute_grid_mesh_info = compute_grid_mesh_info + cls.position_mesh_info = position_mesh_info cls.compute_grid_ghosts = compute_grid_ghosts cls.compute_grid_size = compute_grid_size @@ -243,15 +245,16 @@ class TestDirectionalAdvection(object): assert grid_size[0] % nparticles == 0 kernel_args = [dt] + position_mesh_info = self.position_mesh_info if boundary == BoundaryCondition.PERIODIC: target = 'no_ghosts' - mesh_info = self.grid_mesh_info + velocity_mesh_info = self.grid_mesh_info view = [slice(0,grid_size[2]), slice(0,grid_size[1]), slice(0,grid_size[0])] elif boundary == BoundaryCondition.NONE: target = 'with_ghosts' - mesh_info = self.compute_grid_mesh_info + velocity_mesh_info = self.compute_grid_mesh_info view = [slice(ghosts[2],grid_size[2]+ghosts[2]), slice(ghosts[1],grid_size[1]+ghosts[1]), slice(ghosts[0],grid_size[0]+ghosts[0])] @@ -271,7 +274,8 @@ class TestDirectionalAdvection(object): known_vars = { 'local_size': local_work_size, - 'mesh_info': mesh_info + 'velocity_mesh_info': velocity_mesh_info, + 'position_mesh_info': position_mesh_info } host_init_buffers = self.host_buffers_init[target] @@ -285,7 +289,7 @@ class TestDirectionalAdvection(object): work_dim=work_dim, rk_scheme=rk_scheme, is_cached=cached, - boundary=boundary, + vboundary=(boundary, boundary), nparticles = nparticles, min_ghosts=min_ghosts, symbolic_mode=False, @@ -299,7 +303,10 @@ class TestDirectionalAdvection(object): variables = ['u','pos'] debug = ['dbg0', 'dbg1'] - for varname in variables+debug: + for varname in variables: + kernel_args.append(device_buffers[varname]) + kernel_args.append(np.uint64(0)) + for varname in debug: kernel_args.append(device_buffers[varname]) if (dynamic_shared_bytes != 0): shared_buffer = cl.LocalMemory(dynamic_shared_bytes) @@ -428,7 +435,7 @@ class TestDirectionalAdvection(object): self._check_kernels(rk_scheme=rk_scheme) if __name__ == '__main__': - TestDirectionalAdvection.setup_class(enable_extra_tests=True, enable_error_plots=True) + TestDirectionalAdvection.setup_class(enable_extra_tests=False, enable_error_plots=True) test = TestDirectionalAdvection() test.test_advection_Euler() diff --git a/hysop/backend/device/codegen/kernels/tests/test_directional_stretching.py b/hysop/backend/device/codegen/kernels/tests/test_directional_stretching.py index d216a7cac..ef41f9b03 100644 --- a/hysop/backend/device/codegen/kernels/tests/test_directional_stretching.py +++ b/hysop/backend/device/codegen/kernels/tests/test_directional_stretching.py @@ -26,8 +26,8 @@ class TestDirectionalStretching(object): compute_grid_ghosts = np.asarray([3*4,0,0]) compute_grid_size = grid_size + 2*compute_grid_ghosts - (A,grid_mesh_info) = _test_mesh_info(typegen,3,0,grid_size) - (B,compute_grid_mesh_info) = _test_mesh_info(typegen,3,compute_grid_ghosts,compute_grid_size) + (A,grid_mesh_info) = _test_mesh_info('grid_mesh_info', typegen,3,0,grid_size) + (B,compute_grid_mesh_info) = _test_mesh_info('compute_grid_mesh_info', typegen,3,compute_grid_ghosts,compute_grid_size) grid_shape = grid_size[::-1] compute_grid_shape = compute_grid_size[::-1] @@ -356,14 +356,15 @@ class TestDirectionalStretching(object): dsk = DirectionalStretchingKernel( typegen=self.typegen, - ftype=self.typegen.fbtype, dim=3, + ftype=self.typegen.fbtype, order=order, direction=direction, - formulation=formulation, - rk_scheme=rk_scheme, is_cached=cached, - boundary=boundary, + is_inplace=True, + boundary=(boundary, boundary), + formulation=formulation, + time_integrator=rk_scheme, symbolic_mode=False, known_vars=known_vars) @@ -381,6 +382,7 @@ class TestDirectionalStretching(object): kernel_args.append(shared_buffer) print '\tGenerating and compiling Kernel...' + dsk.edit() source = dsk.__str__() prg = cl.Program(self.typegen.context, source) prg.build(devices=[self.typegen.device]) diff --git a/hysop/backend/device/opencl/opencl_array_backend.py b/hysop/backend/device/opencl/opencl_array_backend.py index e0fe9fc1b..981cb7ec6 100644 --- a/hysop/backend/device/opencl/opencl_array_backend.py +++ b/hysop/backend/device/opencl/opencl_array_backend.py @@ -218,14 +218,26 @@ class OpenClArrayBackend(ArrayBackend): def short_description(self): return ':OpenClBackend: id={}, ctx={}, allocator={}[{}], queue={}, HostBackend[id={}, allocator={}[{}]]'.format( - hash_id(self), + self.identifier(), hash_id(self._context), self._allocator.__class__.__name__, hash_id(self._allocator), hash_id(self._default_queue), - hash_id(self.host_array_backend), + self.host_array_backend.identifier(), self.host_array_backend.allocator.__class__.__name__, hash_id(self.host_array_backend.allocator)) - + + def __eq__(self, other): + if not other.__class__ == self.__class__: + return NotImplemented + eq = (self._context is other._context) + eq &= (self._default_queue is other._default_queue) + eq &= (self._allocator is other._allocator) + eq &= (self.host_array_backend is other.host_array_backend) + return eq + def __ne__(self): + return not (self == other) + def __hash__(self): + return id(self._context) ^ id(self._default_queue) ^ id(self.allocator) ^ id(self.host_array_backend) def __init__(self, cl_env=None, queue=None, allocator=None, host_array_backend=None): diff --git a/hysop/backend/device/opencl/operator/directional/advection_dir.py b/hysop/backend/device/opencl/operator/directional/advection_dir.py index 4ce3c22aa..04ad728fe 100644 --- a/hysop/backend/device/opencl/operator/directional/advection_dir.py +++ b/hysop/backend/device/opencl/operator/directional/advection_dir.py @@ -124,10 +124,11 @@ class OpenClDirectionalAdvection(OpenClDirectionalOperator): vdx = velocity_mesh_info[1].value['dx'][0] advection_ghosts = int(npw.ceil(self.cfl * vdx)) + assert (advection_ghosts >= 1) - advected_fields_in = {field: self.input_discrete_fields[field] + dadvected_fields_in = {field: self.input_discrete_fields[field] for field in self.advected_fields_in} - advected_fields_out = {field: self.output_discrete_fields[field] + dadvected_fields_out = {field: self.output_discrete_fields[field] for field in self.advected_fields_out} fields_in_mesh_info = [ self.input_mesh_info[field] @@ -140,8 +141,15 @@ class OpenClDirectionalAdvection(OpenClDirectionalOperator): for field in fields_in_mesh_info + fields_out_mesh_info: assert field[1].vars['dx'][0] == fdx assert field[1].vars['global_mesh'].vars['xmin'][0] == xmin - - assert (advection_ghosts >= 1) + + self.dvelocity = dvelocity + self.dadvected_fields_in = dadvected_fields_in + self.dadvected_fields_out = dadvected_fields_out + + self.velocity_mesh_info = velocity_mesh_info + self.fields_in_mesh_info = fields_in_mesh_info + self.fields_out_mesh_info = fields_out_mesh_info + self.advection_ghosts = advection_ghosts @debug @@ -149,7 +157,7 @@ class OpenClDirectionalAdvection(OpenClDirectionalOperator): requests = super(OpenClDirectionalAdvection,self).get_work_properties() precision = self.cl_env.precision - request, mesh = MemoryRequest.dfield_like(a=advected_fields_in.values()[0], + request, mesh = MemoryRequest.dfield_like(a=self.dadvected_fields_in.values()[0], dtype=precision, ghosts=None, ncomponents=1) requests.push_mem_request('position', request) diff --git a/hysop/backend/host/fortran/operator/diffusion.py b/hysop/backend/host/fortran/operator/diffusion.py index 0d9e4cc31..891c19dc6 100644 --- a/hysop/backend/host/fortran/operator/diffusion.py +++ b/hysop/backend/host/fortran/operator/diffusion.py @@ -48,7 +48,10 @@ class DiffusionFFTW(FortranFFTWOperator): self.input_field = input_field self.output_field = output_field self.viscosity = viscosity - + + + def initialize(self, **kwds): + super(DiffusionFFTW,self).initialize(**kwds) dim = self.dim if (dim==2): self._solve = self._solve_2d @@ -57,6 +60,7 @@ class DiffusionFFTW(FortranFFTWOperator): else: raise AttributeError(dim + "D case not yet implemented.") + @debug def discretize(self): if self.discretized: @@ -82,7 +86,7 @@ class DiffusionFFTW(FortranFFTWOperator): """ Solve 3D diffusion problem """ dt = simulation.time_step - ghosts = self.topology.ghosts() + ghosts = self.topology.ghosts self.dout.data = \ fftw2py.solve_diffusion_3d(self.viscosity * dt, self.din.data[0], diff --git a/hysop/backend/host/fortran/operator/fortran_fftw.py b/hysop/backend/host/fortran/operator/fortran_fftw.py index 1f197df40..b2aa556ef 100644 --- a/hysop/backend/host/fortran/operator/fortran_fftw.py +++ b/hysop/backend/host/fortran/operator/fortran_fftw.py @@ -25,20 +25,21 @@ class FortranFFTWOperator(ComputationalGraphOperator): check_instance(output_vars, dict, keys=Field, values=CartesianDescriptors) domain = self.input_vars.keys()[0].domain + self.dim = domain.dimension + self.domain = domain + + def handle_topologies(self): + super(FortranFFTWOperator,self).handle_topologies() + topology = self.input_vars.values()[0] - for (field,topo) in input_vars.iteritems(): + domain = self.domain + for (field,topo) in self.input_vars.iteritems(): assert topo is topology, 'topology mismatch' assert field.domain is domain, 'domain mismatch' - for (field,topo) in output_vars.iteritems(): + for (field,topo) in self.output_vars.iteritems(): assert topo is topology, 'topology mismatch' assert field.domain is domain, 'domain mismatch' - - self.dim = domain.dimension - self.domain = domain self.topology = topology - - def initialize(self, **kwds): - super(FortranFFTWOperator,self).initialize(**kwds) @debug def get_field_requirements(self): @@ -60,6 +61,7 @@ class FortranFFTWOperator(ComputationalGraphOperator): if self.discretized: return super(FortranFFTWOperator,self).discretize() + self._fftw_discretize() @debug @@ -105,7 +107,7 @@ class FortranFFTWOperator(ComputationalGraphOperator): assert (topo.mesh.resolution == localres).all(), 'Local resolution mismatch.' assert (topo.mesh.start() == global_start).all(), 'Global start mismatch.' msg = 'Ghosts points not yet implemented for fortran fftw operators.' - assert (topo.ghosts() == 0).all(), msg + assert (topo.ghosts == 0).all(), msg @classmethod def supports_multiple_topologies(cls): diff --git a/hysop/backend/host/fortran/operator/poisson.py b/hysop/backend/host/fortran/operator/poisson.py index a4439a9f9..a583f0fa5 100644 --- a/hysop/backend/host/fortran/operator/poisson.py +++ b/hysop/backend/host/fortran/operator/poisson.py @@ -55,11 +55,16 @@ class PoissonFFTW(FortranFFTWOperator): self.velocity = velocity self.vorticity = vorticity - dim = velocity.domain.dimension + def initialize(self, **kwds): + super(PoissonFFTW,self).initialize(**kwds) + dim = self.dim if (dim==2): self._solve = self._solve_2d elif (dim==3): self._solve = self._solve_3d + + if (dim!=3) and (self.projection!=FieldProjection.NONE): + raise ValueError('Velocity reprojection only available in 3D.') def available_methods(self): return PoissonFFTW.__available_methods @@ -70,8 +75,6 @@ class PoissonFFTW(FortranFFTWOperator): def handle_method(self, method): super(PoissonFFTW,self).handle_method(method) projection = method.pop(FieldProjection) - if (self.dim!=3) and (projection!=FieldProjection.NONE): - raise ValueError('Velocity reprojection only available in 3D.') if projection == FieldProjection.NONE: self._do_project = lambda simu: False @@ -81,6 +84,7 @@ class PoissonFFTW(FortranFFTWOperator): freq = projection assert freq>=1 self._do_project = lambda simu: ((simu.current_iteration % freq)==0) + self.projection = projection assert not method, 'Unused method keywords {}.'.format(method.keys()) @debug @@ -113,8 +117,8 @@ class PoissonFFTW(FortranFFTWOperator): """ Solve 3D poisson problem, no projection, no correction """ # Solves Poisson equation using usual dvorticity - ghosts_v = self.output_vars[self.velocity].ghosts() - ghosts_w = self.input_vars[self.vorticity].ghosts() + ghosts_v = self.output_vars[self.velocity].ghosts + ghosts_w = self.input_vars[self.vorticity].ghosts self.dvelocity.data =\ fftw2py.solve_poisson_3d(self.dvorticity.data[0], self.dvorticity.data[1], diff --git a/hysop/backend/host/host_allocator.py b/hysop/backend/host/host_allocator.py index 1ed0935dd..3a7630962 100644 --- a/hysop/backend/host/host_allocator.py +++ b/hysop/backend/host/host_allocator.py @@ -1,4 +1,5 @@ +from hysop.deps import cpuinfo from hysop.constants import default_order from hysop.core.memory.allocator import AllocatorBase from hysop.backend.host.host_buffer import HostBuffer @@ -28,4 +29,4 @@ class HostAllocator(AllocatorBase): return HostMemoryPool(allocator=self, name=name, **kwds) default_host_allocator = HostAllocator() -default_host_mempool = default_host_allocator.memory_pool(name='default host pool') +default_host_mempool = default_host_allocator.memory_pool(name=cpuinfo.cpuinfo.get_cpu_info()['brand']) diff --git a/hysop/backend/host/host_array_backend.py b/hysop/backend/host/host_array_backend.py index b40b34c14..604ae3076 100644 --- a/hysop/backend/host/host_array_backend.py +++ b/hysop/backend/host/host_array_backend.py @@ -80,7 +80,7 @@ class HostArrayBackend(ArrayBackend): def short_description(self): return ':HostBackend: id={}, allocator={}[{}]'.format( - hash_id(self), self.allocator.__class__.__name__, hash_id(self.allocator)) + self.identifier(), self.allocator.__class__.__name__, hash_id(self.allocator)) ############################ diff --git a/hysop/core/arrays/array_backend.py b/hysop/core/arrays/array_backend.py index 6ee18fac8..08a9248cd 100644 --- a/hysop/core/arrays/array_backend.py +++ b/hysop/core/arrays/array_backend.py @@ -149,6 +149,17 @@ class ArrayBackend(object): check_instance(allocator, AllocatorBase) super(ArrayBackend,self).__init__(**kwds) self._allocator = allocator + + + def __eq__(self, other): + if not other.__class__ == self.__class__: + return NotImplemented + eq = (self._allocator is other._allocator) + return eq + def __ne__(self): + return not (self == other) + def __hash__(self): + return id(self._allocator) @abstractmethod def get_host_array_backend(self): @@ -160,6 +171,9 @@ class ArrayBackend(object): def short_description(self): pass + def identifier(self): + return str(hex(hash(self)))[2:6] + def get_allocator(self): """ Get the allocated associated to this backend. diff --git a/hysop/core/graph/computational_graph.py b/hysop/core/graph/computational_graph.py index 3ea638fe0..9f7cffc2e 100644 --- a/hysop/core/graph/computational_graph.py +++ b/hysop/core/graph/computational_graph.py @@ -113,8 +113,7 @@ class ComputationalGraph(ComputationalGraphNode): topologies[backend] = set() topologies[backend].update(topos) return topologies - - + @debug @not_initialized def push_nodes(self, *args): @@ -171,6 +170,7 @@ class ComputationalGraph(ComputationalGraphNode): if is_root: field_requirements = self.get_field_requirements() field_requirements.build_topologies() + self.handle_topologies() self._build_graph(outputs_are_inputs=outputs_are_inputs, current_level=0) self.initialized=True @@ -189,6 +189,13 @@ class ComputationalGraph(ComputationalGraphNode): if (self.is_root and __VERBOSE__) or __DEBUG__: print self.field_requirements_report(requirements) return requirements + + @debug + def handle_topologies(self): + super(ComputationalGraph, self).handle_topologies() + for node in self.nodes: + node.handle_topologies() + @staticmethod def _op_info(op, jmp=False): diff --git a/hysop/core/graph/computational_node.py b/hysop/core/graph/computational_node.py index 8ca467606..a933f8213 100644 --- a/hysop/core/graph/computational_node.py +++ b/hysop/core/graph/computational_node.py @@ -27,6 +27,19 @@ def base_initialized(f): return f(*args,**kargs) return _check +def topology_handled(f): + assert callable(f) + @wraps(f) + def _check(*args,**kargs): + self = args[0] + msg = 'Cannot call {}.{}() on node \'{}\' because {}'\ + .format(self.__class__.__name__,f.__name__,self.name,'{}') + if not self.topology_handled: + reason='this self.handle_topologies() has not been called yet.' + raise RuntimeError(msg.format(reason)) + return f(*args,**kargs) + return _check + class ComputationalGraphNode(OperatorBase): """ Interface of an abstract computational graph node. @@ -126,9 +139,10 @@ class ComputationalGraphNode(OperatorBase): self.output_vars = output_vars self.base_method = method - self.initialized = False - self.discretized = False - self.ready = False + self.initialized = False + self.topology_handled = False + self.discretized = False + self.ready = False self._base_initialized = False if (input_vars or output_vars): @@ -353,6 +367,15 @@ class ComputationalGraphNode(OperatorBase): """ self.method = copy.deepcopy(method) + @debug + def handle_topologies(self): + """ + Called after all topologies have been set up. + Topologies are available as values of self.input_vars + and self.output_vars and are mapped by continuous Field. + """ + self.topology_handled = True + @abstractmethod def get_field_requirements(self): """ @@ -465,7 +488,7 @@ class ComputationalGraphNode(OperatorBase): return method @debug - @initialized + @topology_handled def discretize(self): """ Discretize this operator. diff --git a/hysop/core/graph/computational_operator.py b/hysop/core/graph/computational_operator.py index 89e862c72..e0df05d35 100644 --- a/hysop/core/graph/computational_operator.py +++ b/hysop/core/graph/computational_operator.py @@ -196,6 +196,20 @@ class ComputationalGraphOperator(ComputationalGraphNode): and self.output_discrete_fields, which contains input and output dicretised fields. """ + if not self.topology_handled: + import warnings + msg= '\nTopologies in operator {} has not been handled yet.' + msg+='\nThis may be the case if this operator was not embedded into ' + msg+='a ComputationalGraph.' + msg=msg.format(self.name) + print + warnings.warn(msg) + print + + requirements = self.get_field_requirements() + requirements.build_topologies() + self.handle_topologies() + super(ComputationalGraphOperator,self).discretize() for field,topology in self.input_vars.iteritems(): self.input_discrete_fields[field] = field.discretize(topology) diff --git a/hysop/core/memory/mempool.py b/hysop/core/memory/mempool.py index 615743e50..836d9bfb3 100644 --- a/hysop/core/memory/mempool.py +++ b/hysop/core/memory/mempool.py @@ -32,7 +32,7 @@ class MemoryPool(object): __metaclass__ = ABCMeta def __init__(self, name, allocator, max_alloc_bytes=None, - mantissa_bits=2, verbose=None, **kwds): + mantissa_bits=4, verbose=None, **kwds): """ Builds a MemoryPool from an allocator. Provides an allocator like interface. diff --git a/hysop/core/mpi/redistribute.py b/hysop/core/mpi/redistribute.py index f0db60394..20c2985a6 100644 --- a/hysop/core/mpi/redistribute.py +++ b/hysop/core/mpi/redistribute.py @@ -186,6 +186,7 @@ class RedistributeOperator(ComputationalGraphOperator): super(RedistributeOperator,self).initialize(topgraph_method) @debug def discretize(self): + self.handle_topologies() super(RedistributeOperator,self).discretize() # Dictionnary of discrete fields to be sent and received v = self.variable diff --git a/hysop/core/mpi/topology.py b/hysop/core/mpi/topology.py index eb5eadf8f..afe862db5 100644 --- a/hysop/core/mpi/topology.py +++ b/hysop/core/mpi/topology.py @@ -83,8 +83,8 @@ class Topology(object): check_instance(backend, Backend) if backend == Backend.HOST: from hysop.core.arrays.all import HostArrayBackend - from hysop.backend.host.host_allocator import HostAllocator - allocator = allocator or HostAllocator() + from hysop.backend.host.host_allocator import default_host_mempool + allocator = allocator or default_host_mempool backend = HostArrayBackend(allocator) elif backend == Backend.OPENCL: from hysop.backend.device.opencl.opencl_tools import get_or_create_opencl_env diff --git a/hysop/deps.py b/hysop/deps.py index 342a42e5c..7abbe217d 100644 --- a/hysop/deps.py +++ b/hysop/deps.py @@ -21,7 +21,7 @@ except ImportError as e: print(msg) import sys, os, subprocess, platform -import resource, psutil, tempfile +import resource, psutil, tempfile, cpuinfo import inspect, functools, operator import hashlib, gzip, copy, types, string import math, re, contextlib -- GitLab