@@ -399,6 +399,17 @@ def has_live_ancestors(self, ctxt: NetworkContext) -> bool:
399399
400400 return False
401401
402+ def sizeInBytes (self ) -> int :
403+ """Returns the size of this VariableBuffer in bytes
404+
405+ Returns
406+ -------
407+ int
408+ Size of this VariableBuffer in bytes
409+
410+ """
411+ return int (np .prod (self .shape ) * (self ._type .referencedType .typeWidth // 8 ))
412+
402413
403414class TransientBuffer (VariableBuffer ):
404415 """Class to represent memory space required by kernels that is not covered by input and output tensors, e.g. im2col buffers in convolutions
@@ -445,6 +456,9 @@ def __repr__(self) -> str:
445456 def fromVariableBuffer (cls , buffer : VariableBuffer ):
446457 ret = cls (name = buffer .name , size = np .prod (buffer .shape ) * buffer ._type .typeWidth // 8 )
447458
459+ def sizeInBytes (self ) -> int :
460+ return int (self .size )
461+
448462
449463class ConstantBuffer (VariableBuffer ):
450464 """Class to represent compile-time constant tensors (weights, biases, other parameters) within Deeploy.
@@ -587,6 +601,9 @@ def __init__(self,
587601 self .TransientBuffer = transientBuffer
588602 self .name = name
589603
604+ self ._maxDynamicSize = {} #: int: Maximum dynamic memory size occupied by live buffers at any point in time
605+ self ._dynamicSize = {} #: int: Current dynamic memory size occupied by live buffers
606+
590607 def dealiasBuffer (self , name : str ) -> str :
591608 """Function to find the underlying aliased VariableBuffer
592609
@@ -2965,8 +2982,7 @@ def generateIOBufferInitializationCode(self) -> str:
29652982 def worstCaseBufferSize (self ):
29662983 """Return the worst-case buffer size occupied by the network implementaiton
29672984 """
2968- # WIESEP: There is no reasonable value for a worst case buffer size without tiling
2969- raise NotImplementedError ("Worst case buffer size is not known or not implemented!" )
2985+ return self .ctxt ._maxDynamicSize
29702986
29712987 # Don't override this
29722988 def generateBufferInitializationCode (self ) -> str :
@@ -3116,54 +3132,6 @@ def generateEngineInitializationCode(self) -> str:
31163132 """
31173133 return ("\n " ).join ([engine .initCode for engine in self .Platform .engines ])
31183134
3119- # Don't override this - Returns parameter size in bytes
3120- def getParameterSize (self ) -> int :
3121- """Return the BYTE size of all static network parameters (weights, biases, parameters,...)
3122-
3123- Returns
3124- -------
3125- int
3126- Size of all network parameters
3127-
3128- Raises
3129- ------
3130- RuntimeError
3131- Raises a RuntimeError if network is not parsed and bound
3132-
3133-
3134- """
3135- if not self .parsed or not self .bound :
3136- raise RuntimeError ('You need to parse and bind the network before getting RAM Size!' )
3137-
3138- size = 0
3139- for _buffer in self .ctxt .globalObjects .values ():
3140- # We do not count structs for now, since they are not properly modeled
3141- if isinstance (_buffer , ConstantBuffer ) and _buffer ._deploy :
3142- size += int ((np .prod (_buffer .shape ) * _buffer ._type .typeWidth // 8 ))
3143-
3144- return size
3145-
3146- # Don't override this - Returns worst case layer and buffering size in bytes
3147- def getTotalSize (self ) -> int :
3148- """Returns total size of the network, consisting of all parameters and intermediate buffer size
3149-
3150- Returns
3151- -------
3152- int
3153- Total network size
3154-
3155- Raises
3156- ------
3157- RuntimeError
3158- Raises a RuntimeError if network is not parsed and bound
3159-
3160-
3161- """
3162- if not self .parsed or not self .bound :
3163- raise RuntimeError ('You need to parse and bind the network before getting RAM Size!' )
3164-
3165- return self .getParameterSize () + self .worstCaseBufferSize
3166-
31673135 def numberOfOps (self , verbose : bool ) -> int :
31683136 """Returns the total number of operations per network inference
31693137
@@ -3584,6 +3552,41 @@ def prepare(self, verbose: CodeGenVerbosity = _NoVerbosity):
35843552 self .backEnd (verbose = verbose )
35853553 self .prepared = True
35863554
3555+ def _printInputOutputSummary (self ):
3556+ log .info ("Input:" )
3557+ for buf in self .inputs ():
3558+ log .info (f" - '{ buf .name } ': Type: { buf ._type .referencedType .typeName } " )
3559+
3560+ log .info ('Output:' )
3561+ for buf in self .outputs ():
3562+ log .info (f" - '{ buf .name } ': Type: { buf ._type .referencedType .typeName } " )
3563+
3564+ def _printMemorySummary (self ):
3565+ log .info ("" )
3566+ log .info ("Memory Usage Report:" )
3567+ log .info (f"Level Total (bytes) (Static + Dynamic) " )
3568+ log .info ("-" * 80 )
3569+
3570+ _worstCaseBufferSize = self .worstCaseBufferSize
3571+ if len (_worstCaseBufferSize ) == 0 :
3572+ _worstCaseBufferSize = {"None" : 0 }
3573+
3574+ for level , dynamicSize in _worstCaseBufferSize .items ():
3575+ staticSize = 0
3576+ for _buffer in self .ctxt .globalObjects .values ():
3577+ # We do not count structs for now, since they are not properly modeled
3578+ if isinstance (_buffer , ConstantBuffer ) or (isinstance (_buffer , VariableBuffer ) and _buffer ._deploy ):
3579+ # SCHEREMO: We only
3580+ if (hasattr (_buffer , "_memoryLevel" ) and _buffer ._memoryLevel == level ) or level == "None" :
3581+ staticSize += int ((np .prod (_buffer .shape ) * _buffer ._type .referencedType .typeWidth // 8 ))
3582+ else :
3583+ log .warning (f"Buffer { _buffer .name } does not have a valid memory level" )
3584+
3585+ total = staticSize + dynamicSize
3586+
3587+ log .info (f"{ level :<22} { total :8,d} "
3588+ f"({ staticSize :6,d} + { dynamicSize :7,d} ) " )
3589+
35873590 def generateFunction (self , verbose : CodeGenVerbosity = _NoVerbosity ) -> str :
35883591 """Helper function to prepare deployment and return generated function code
35893592
@@ -3596,19 +3599,13 @@ def generateFunction(self, verbose: CodeGenVerbosity = _NoVerbosity) -> str:
35963599 log .info ("Deeploy Code Generation" )
35973600 log .info ("=" * 80 )
35983601
3599- log .info ('Input:' )
3600- for name in self .inputTypes .keys ():
3601- buf = self .ctxt .lookup (name )
3602- log .info (f" - '{ name } ': Type: { buf ._type .referencedType .typeName } " )
3603-
3604- log .info ('Output:' )
3605- for buf in self .outputs ():
3606- log .info (f" - '{ buf .name } ': Type: { buf ._type .referencedType .typeName } " )
3602+ self ._printInputOutputSummary ()
36073603
36083604 num_ops = self .numberOfOps (verbose = True )
36093605 log .info ("-" * 80 )
36103606
36113607 log .info (f"Number of Ops. : { num_ops } " )
3612- log .info (f"Model Parameters : { self .getParameterSize ()} " )
3608+
3609+ self ._printMemorySummary ()
36133610
36143611 return self .generateInferenceCode ()
0 commit comments