-
Notifications
You must be signed in to change notification settings - Fork 394
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
Surf heat balance arrays refactoring #8744
Conversation
state.dataSurface->SurfOutWindSpeed(SurfNum) = state.dataLoopNodes->Node(state.dataSurface->SurfLinkedOutAirNode(SurfNum)).OutAirWindSpeed; | ||
state.dataSurface->SurfOutWindDir(SurfNum) = state.dataLoopNodes->Node(state.dataSurface->SurfLinkedOutAirNode(SurfNum)).OutAirWindDir; | ||
state.dataSurface->SurfOutDryBulbTemp(SurfNum) = | ||
state.dataLoopNodes->Node(state.dataSurface->SurfLinkedOutAirNode(SurfNum)).OutAirDryBulb; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should do this type of formatting at this time. IMO, it would be better to leave the lines as one and to shorten some of the variable and field names, .e.g.,
s.surface->OutDryBulbTemp(SurfNum) = s.loopNodes->Node(s.surface->LinkedOutAirNode(SurfNum)).OutAirDryBulb;
@@ -2137,7 +2156,7 @@ void InitThermalAndFluxHistories(EnergyPlusData &state) | |||
auto &Surface(state.dataSurface->Surface); | |||
|
|||
// First do the "bulk" initializations of arrays sized to NumOfZones | |||
state.dataHeatBal->ZoneMRT = 23.0; // module level array | |||
state.dataHeatBal->ZoneMRT = 23.0; // module level array | |||
state.dataHeatBalFanSys->MAT = 23.0; // DataHeatBalFanSys array | |||
state.dataHeatBalFanSys->ZT = 23.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should avoid using these array initializers and initialize explicitly using a loop. This should also allow us to combine these different initialization loops into a single loop.
@@ -2137,7 +2156,7 @@ void InitThermalAndFluxHistories(EnergyPlusData &state) | |||
auto &Surface(state.dataSurface->Surface); | |||
|
|||
// First do the "bulk" initializations of arrays sized to NumOfZones | |||
state.dataHeatBal->ZoneMRT = 23.0; // module level array | |||
state.dataHeatBal->ZoneMRT = 23.0; // module level array | |||
state.dataHeatBalFanSys->MAT = 23.0; // DataHeatBalFanSys array | |||
state.dataHeatBalFanSys->ZT = 23.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, should use a symbolic constexpr
rather than a literal 23.0.
@@ -2328,7 +2347,7 @@ void EvalOutsideMovableInsulation(EnergyPlusData &state) | |||
state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(1)).Roughness; | |||
continue; | |||
} | |||
auto const MaterialIndex(state.dataSurface->Surface(SurfNum).MaterialMovInsulExt); | |||
auto const MaterialIndex(state.dataSurface->SurfMaterialMovInsulExt(SurfNum)); | |||
auto const MaterialGroupNum(state.dataMaterial->Material(MaterialIndex).Group); | |||
state.dataHeatBalSurf->SurfMovInsulExtPresent(SurfNum) = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's shorter and clearer to write int
than auto
.
@@ -4970,7 +4970,7 @@ void FigureSolarBeamAtTimestep(EnergyPlusData &state, int const iHour, int const | |||
|
|||
for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { | |||
|
|||
if (!state.dataSurface->Surface(SurfNum).ShadowingSurf && | |||
if (!state.dataSurface->SurfIsShadowing(SurfNum) && | |||
(!state.dataSurface->Surface(SurfNum).HeatTransSurf || !state.dataSurface->Surface(SurfNum).ExtSolar)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is IsShadowing
a surface-level array while HeatTransSurf
and ExtSolar
are fields in the Surface array? It seems like these fields have similar usages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@amirroth HeatTransSurf
and ExtSolar
are assigned during input processing and saved in SurfaceTmp
(e.g.ExtSolar = UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "SunExposed")
). With all surface data being read, SurfaceTmp
arrays are sorted and copied to a new Surface
array. So these fields remain as fields not arrays because otherwise, I'll have to sort the arrays. IsShadowing
is evaluated and assigned afterward. I don't know if it's worthwhile or good practice to move it out from a field to an array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not suggesting removing it from the class, I was suggesting replicating it in its own array if the use cases warrants it. If not (maybe surfaces are sorted so that you don't have to explicitly check for these conditions or maybe we are using explicit surface lists that only include surfaces with these conditions) then it doesn't matter.
@@ -771,7 +771,7 @@ void AllocateModuleArrays(EnergyPlusData &state) | |||
state.dataHeatBal->CosIncAngHR.dimension(24, state.dataSurface->TotSurfaces, 0.0); | |||
state.dataHeatBal->CosIncAng.dimension(state.dataGlobal->NumOfTimeStepInHour, 24, state.dataSurface->TotSurfaces, 0.0); | |||
state.dataHeatBal->SurfAnisoSkyMult.dimension(state.dataSurface->TotSurfaces, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I would also like us to stop using dimension
and replace with allocate
and explicit loop initialization. This will allow us to combine the initializations multiple arrays into a single loop, which improves performance.
@mjwitte This branch is ready for review. The PR overview lists a walkthrough of the changes and diffs. The CI performance is not green... but tested locally |
Hmmm. Surprising that you are not seeing any improvements on other models, although 8% on a big model is good. Maybe some other things like data-dependent branches are getting in the way of the speedups. Which functions are you expecting to see speedup on? |
src/EnergyPlus/DaylightingManager.cc
Outdated
if (!surface.ShadowSurfPossibleObstruction) return false; // Do Consider separate octree without filtered surfaces | ||
int const ObsSurfNum = surface.Index; | ||
if (!state.dataSurface->SurfShadowPossibleObstruction(ObsSurfNum)) return false; // Do Consider separate octree without filtered surfaces |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since a single instance of Surface
is a parameter to this lambda function, is it possible that the lookup of state.dataSurface->SurfShadowPossibleObstruction(ObsSurfNum)
is more work than fetching surface.ShadowSurfPossibleObstruction
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is. However, given that this function was written when all data fields were part of the SurfaceData
struct, it is also possible that this lambda
needs to be written to take a SurfIdx
argument rather than a Surface &
argument. Either way, I don't think this is a huge immediate problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I asked about this is because the performance test for 15zonePSZ shows about 38 million more "cost" on this branch than develop (0.24% more). About 10m is coming from daylighting functions. Small overall, but just curious why these code changes would result in any increase at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I found this piece suspicious when I rewrote this part to fit the new array structure into the lambda function. I actually had to add an Index
to Surface
to find the SurfNum. (Potentially Index
should be useful as there are still places we find Surface Index by Name
using FindItemInList
)
I didn't realize it would create such performance reduction. I actually thought about rewriting the lambda function, but the syntax at this part looked quite confusing to me. Since it's potentially a performance bottleneck I'll take another look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. This one change shouldn't be that much, unless daylighting functions are called much more frequently than they need to be. Overall, the increase in instruction count probably has to do with the fact that we have to call many more array constructors & initializers. Some of that will go away if we initialize explicitly using one or several large loops as opposed to using dimension
. Definitely things to keep markers on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few things.
- It's fine to have both a
SurfShadowPossibleObstruction
array and aSurfShadowPossibleObstruction
field. If they don't change over the life of the model, then there is no overhead associated with keeping them in sync. - It's also probably fine to leave
SurfShadowPossibleObstruction
as a field since I don't imagine it is used in the kinds of loops that would be amenable to vectorization anyway. - You could change the
PierceSurface
/SurfaceOctree
functions to takeSurfIndex
instead ofSurface &
as an argument. If we are worried about the performance of those functions there are possibly other things we can do to make them faster, not sure if these mods belong in this branch/PR.
@mjwitte So I reverted the changes of two shadowing fields to arrays. Testing locally before and after using 15zonePSZ, comparing develop and this branch, I can't see any meaningful and consistent performance difference. I also used local timers to test the daylighting functions, and the run time difference is marginal (<0.5%). I'll wait for CI to tell the updated performance difference then. |
src/EnergyPlus/DataSurfaces.hh
Outdated
Array1D<Real64> SurfIntConvCoeff; // Interior Convection Coefficient pointer (different data structure) when being overridden | ||
Array1D<Real64> SurfExtConvCoeff; // Exterior Convection Coefficient pointer (different data structure) when being overridden |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be integers. That should reduce the eio diffs. Without seeing the declarations, I had assumed SurfIntConvCoeff
was the actual convection coefficient value. Perhaps these should be renamed, e.g. SurfIntConvCoeffIndex
?
…yPlus into surf-hb-struct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xuanluo113 I pushed up a few minor doc edits to clean up font and equation width issues (that were present before but were more pronounced with the longer variable names). Once CI comes back clean, I will merge this.
Pull request overview
This branch including the refactoring of moving run time heat balance variables from SurfaceData object to surface arrays. The following refactorings are also made along with the restructuring.
GetMovableInsulationData
andGetShadingSurfReflectanceData
afterSurface
is allocated and sorted. The related property arrays do not need to be assigned toSurfaceTmp
array and copied toSurface
later.Encl
arrays toDataHeatBal
namespaces.dataHeatBalSurf->ZoneMRT
arrays withthe same meaning asdataHeatBal->ZoneMRT
arrays to reduce data copies at each time step.DataSurface
andDataHeatBal
namespaces (e.g.QS
->EnclSolSWRad
,QL
->EnclRadQLWRad
).state.dataSolarShading->MustAllocSolarShading
orif (!allocated(state.dataHeatBal->EnclSolQSWRad))
and (conditionally) allocate the arrays once during simulation setup. These conditions do not have to be checked at every time step.sum_product_sub(state.dataSurface->Surface, &SurfaceData::Area, &SurfaceData::OutDryBulbTemp, SurfPtrARR)
to manual calc of sum product (asSurfOutDryBulbTemp
field is not in SurfaceData domain).The CI performance is not green. Other than items 6 & 7 I don't see what other changes may possibly reduce the performance.
There are two parts of text diffs causing by:
state.dataSurface->SurfExtConvCoeff(SurfLoop)
instead ofSurface(SurfLoop).ExtConvCoeff
changes the eio printout from 0.0 to 0 for zero values.DataHeatBalSurf
toDataHeatBal
, causing the reordering of the RDD files.There are still quite a few related array reordering, renaming and initialization issue to fix including:
DataHeatBalance
andDataHeatBalanceSurf
dimension
for initialization.NumOfZones
,NumOfSolarEnclosures
, etc. (in comparing toTotSurfaces
?)that I plan to do in some other branch later.
Pull Request Author
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
Reviewer
This will not be exhaustively relevant to every PR.