Differences between revisions 2 and 3
Deletions are marked like this. Additions are marked like this.
Line 4: Line 4:
Each face had a normal vector and area stored in the nx,ny,nz,orig_area members of the FACE struct.

mris_fix_topology has a hot loop
mris_fix_topology has a hot loop, which does unnecessary calculations of the face normals
Line 9: Line 7:

_: _: a computeDefectContext is constructed here
Line 16: Line 12:
_:_:_: _: mrisComputeDefectLogLikelihood, which calls _:_:_:_: mrisComputeDefectLogLikelihood, which calls
Line 18: Line 14:
_:_:_: _: _: mrisComputeDefectMRILogUnlikelihood, which _:_:_:_:_: mrisComputeDefectMRILogUnlikelihood, which
Line 20: Line 16:
_:_:_: _: _:_: does an expensive computation all the face normals for ALL the faces _:_:_:_:_:_: does an expensive computation all the face normals for ALL the faces
Line 22: Line 18:
_:_:_: _: _:_: does two other expensive steps, which only use a few of the face normals _:_:_:_:_:_: does two other expensive steps, which only use a few of the face normals

To simplify, the original code does this

    loop

        for all fno normal[fno] = f (inputs)

        for a few fno use normal[fno]

        change some inputs

    end loop

    change some inputs

    use some normal[fno]

Since only a few of the face normals are used, it is a waste of time to calculate all of them every time around the loop!

This is replaced by code that does

    loop

        for all fno __normal[fno].deferred = true__

        for a few fno __if normal[fno].deferred normal[fno] = f (inputs); normal[fno].deferred = false__

        change some inputs

    end loop

    __for a few fno if normal[fno].deferred normal[fno] = f (inputs); normal[fno].deferred = false__

    change some inputs

    use some normal[fno]

A variety of techniques have been used.

Deferring calculations until needed

mris_fix_topology has a hot loop, which does unnecessary calculations of the face normals

mrisComputeOptimalRetessellation and mrisComputeRandomRetessellation have a similar structure

_:_: then it loops over a set of patches, or iterates on one patch. For each patch it calls

_:_:_: mrisDefectPatchFitness, which calls

_:_:_:_: mrisComputeDefectLogLikelihood, which calls

_:_:_:_:_: mrisComputeDefectMRILogUnlikelihood, which

_:_:_:_:_:_: does an expensive computation all the face normals for ALL the faces

_:_:_:_:_:_: does two other expensive steps, which only use a few of the face normals

To simplify, the original code does this

  • loop
    • for all fno normal[fno] = f (inputs) for a few fno use normal[fno] change some inputs
    end loop change some inputs use some normal[fno]

Since only a few of the face normals are used, it is a waste of time to calculate all of them every time around the loop!

This is replaced by code that does

  • loop
    • for all fno normal[fno].deferred = true

      for a few fno if normal[fno].deferred normal[fno] = f (inputs); normal[fno].deferred = false change some inputs

    end loop

    for a few fno if normal[fno].deferred normal[fno] = f (inputs); normal[fno].deferred = false change some inputs use some normal[fno]

MorphoOptimizationProject_BetterSerialCode_DeferCalculations (last edited 2021-09-22 09:46:34 by DevaniCordero)