1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
@*
OpenMP.tmpl
Created by Graham Dennis on 2007-12-18.
Copyright (c) 2007-2012, Graham Dennis
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*@
@extends xpdeint.Features._Feature
@from xpdeint.CallOnceGuards import callOnceGuard
@def description: OpenMP
@attr featureName = 'OpenMP'
@attr uselib = ['openmp']
@@callOnceGuard
@def includes
@#
@super
@#
#ifdef _OPENMP
#include <omp.h>
#endif
@#
@end def
@def mainBegin($dict)
@#
@if $threadCount
#ifdef _OPENMP
omp_set_num_threads($threadCount);
#endif
@end if
@#
@end def
@def loopOverVectorsWithInnerContentTemplateBegin($dict)
@#
@if 'UNVECTORISABLE' in dict['templateString']
@return
@end if
#ifdef _OPENMP
#pragma omp parallel for
#endif
@#
@end def
@def loopOverVectorsWithInnerContentBegin($dict)
@#
@if 'UNVECTORISABLE' in dict['loopCode']
@return
@end if
@#
@set $vectors = dict['vectors']
@set $index_pointers = [c'_${vector.id}_index_pointer' for vector in vectors]
@#
bool __initialised = false;
#ifdef _OPENMP
@set suffix = ''
@if index_pointers
@set suffix = c' private(${", ".join(index_pointers)})'
@end if
#pragma omp parallel for firstprivate(__initialised)${suffix}
#endif
@#
@end def
@def loopOverVectorsWithInnerContentEnd($dict)
@#
@if 'UNVECTORISABLE' in dict['loopCode']
@return
@end if
@#
@set $vectors = dict['vectors']
@#
if (!__initialised) {
@for vector in vectors
_${vector.id}_index_pointer = _i0 * _${vector.id}_ncomponents;
@end for
__initialised = true;
}
@end def
@def loopOverFieldInBasisWithVectorsAndInnerContentLoopOpenBegin($dict)
@#
@# What about the copyDeltaA code? Is that parallel-safe?
@# If we have already parallelised a dimension, don't do any more
@# and if we can't parallelise, don't.
@if 'UNVECTORISABLE' in dict['loopCode'] or 'openMPParallelDimRep' in dict
@return
@end if
@#
@set vectorOverrides = dict['vectorOverrides']
@set field = dict['field']
@set basis = dict['basis']
@set dimRep = dict['dimRep']
@set dimensionsBeingIntegratedOver = set()
@if vectorOverrides
@silent dimensionsBeingIntegratedOver.update(field.dimensions)
@for dim in dimensionsBeingIntegratedOver.copy()
@for vector in vectorOverrides
@if vector.field.hasDimension(dim)
@silent dimensionsBeingIntegratedOver.discard(dim)
@break
@end if
@end for
@end for
@end if
@#
@# If this dim rep is being integrated over, we can't parallelise this dimension, so return
@for dim in dimensionsBeingIntegratedOver
@if dim.inBasis(basis) == dimRep
@return
@end if
@end for
@#
@for fieldDimRep in reversed(field.inBasis(basis))
@# If there's pre or post dimension loop opening code, we can't trust that we can parallelise this.
@if fieldDimRep.name in dict['preDimensionLoopOpeningCode'] or fieldDimRep.name in dict['postDimensionLoopClosingCode']
@return
@end if
@#
@if fieldDimRep == dimRep
@break
@end if
@end for
@#
@silent dict['openMPParallelDimRep'] = dict['dimRep']
@#
@set $vectorsNotRequiringExplicitIndexPointers = dict['vectorsNotRequiringExplicitIndexPointers']
@set $private_variables = [c'_${vector.id}_index_pointer' for vector in vectorsNotRequiringExplicitIndexPointers]
@for vector in dict['vectorOverrides']
@silent private_variables.extend(vector.components)
@end for
@#
@set suffix = ''
@if private_variables
@set suffix = c' private(${", ".join(private_variables)})'
@end if
bool __initialised = false;
#ifdef _OPENMP
#pragma omp parallel for firstprivate(__initialised)${suffix}
#endif
@#
@end def
@def loopOverFieldInBasisWithVectorsAndInnerContentLoopOpenEnd($dict)
@#
@# Only complete initialisation for the parallel loop if this is that loop
@if dict.get('openMPParallelDimRep') is not dict['dimRep']
@return
@end if
@#
@set $vectorsNotRequiringExplicitIndexPointers = dict['vectorsNotRequiringExplicitIndexPointers']
@set $dimRep = dict['dimRep']
@set $field = dict['field']
@set $basis = dict['basis']
@#
if (!__initialised) {
@for vector in vectorsNotRequiringExplicitIndexPointers
_${vector.id}_index_pointer = ${dimRep.loopIndex} * ${vector.field.localPointsInDimensionsAfterDimRepInBasis(dimRep, basis)} * _${vector.id}_ncomponents;
@for prefixDimRep in field.inBasis(basis)
@if prefixDimRep is dimRep
@break
@end if
_${vector.id}_index_pointer += ${prefixDimRep.loopIndex} * ${vector.field.localPointsInDimensionsAfterDimRepInBasis(prefixDimRep, basis)} * _${vector.id}_ncomponents;
@end for
@end for
__initialised = true;
}
@#
@end def
|