Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,29 @@ def _NCHWtoNHWC_fun(graph: gs.Graph, match: Match, name: str, default_channels_f
if node.op in ["Conv", "RequantizedConv"]:
# In the case of Conv: [weights, opt. bias], RequantizedConv: [weights, mul, add, opt. shift]
for tensor in node.inputs[1:]:
_transformLayoutConst(tensor, spatialDims, default_channels_first)

# Standard case: The weight is a direct constant input.
if isinstance(tensor, gs.Constant):
const_to_transform = tensor
# MeZO case: The weight is produced by a Perturb node.
elif isinstance(tensor, gs.Variable):
producer_node = None
for n in graph.nodes:
if tensor in n.outputs:
producer_node = n
break

if producer_node and producer_node.op in ["PerturbNormal", "PerturbUniform"]:
# Find the original constant that feeds the Perturb node.
const_to_transform = producer_node.inputs[0]

# If we found a constant, transpose it. The Perturb node will inherit the new layout.
if const_to_transform and isinstance(const_to_transform, gs.Constant):
# Only apply layout transformation to multi-dimensional tensors (i.e., weights)
if len(const_to_transform.shape) > 1:
_transformLayoutConst(const_to_transform, spatialDims, default_channels_first)
if producer_node:
tensor.shape = tuple(const_to_transform.shape)
node.attrs["channels_first"] = default_channels_first

return graph
Expand Down
5 changes: 3 additions & 2 deletions Deeploy/DeeployTypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2884,10 +2884,11 @@ def generateIOBufferInitializationCode(self) -> str:

callStack += "static const uint32_t " + self.ctxt._mangle("num_inputs") + f" = {len(inputs)};"
callStack += "static const uint32_t " + self.ctxt._mangle("num_outputs") + f" = {len(outputs)};"

callStack += "static const uint32_t seed = 12345;" # fixed seed for reproducibility
callStack += "static const uint32_t perturbation_sign = 1;" # fixed sign for reproducibility
callStack += "extern void* " + self.ctxt._mangle("inputs") + f"[{len(inputs)}];"
callStack += "extern void* " + self.ctxt._mangle("outputs") + f"[{len(outputs)}];"

callStack += "static const uint32_t " + self.ctxt._mangle("inputs_bytes") + f"[{len(inputs)}] = " + "{"

numBytes = []
Expand Down
3 changes: 3 additions & 0 deletions Deeploy/Targets/GAP9/Bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@
GAP9ConcatBindings = [
NodeBinding(ConcatChecker([PointerClass(type), PointerClass(type)], [PointerClass(type)]),
ConcatTemplate.referenceTemplate, GAP9ClusterTransformer) for type in IntegerDataTypes
] + [
NodeBinding(ConcatChecker([PointerClass(float32_t), PointerClass(float32_t)], [PointerClass(float32_t)]),
ConcatTemplate.referenceTemplate, GAP9ClusterTransformer)
]

GAP9iRMSNormBindings = [
Expand Down
37 changes: 37 additions & 0 deletions Deeploy/Targets/Generic/Layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -709,3 +709,40 @@ def computeOps(self):
numPx = opRep['dim_im_out_x']

return numPx * opsPerPx


class PerturbNormalLayer(ONNXLayer):
def __init__(self, maps: List[NodeMapper]):
super().__init__(maps)

def computeOps(self):
return self.mapper.parser.operatorRepresentation['size']

class PerturbUniformLayer(ONNXLayer):
def __init__(self, maps: List[NodeMapper]):
super().__init__(maps)

def computeOps(self):
return self.mapper.parser.operatorRepresentation['size']

class PerturbEggrollLayer(ONNXLayer):
def __init__(self, maps: List[NodeMapper]):
super().__init__(maps)

def computeOps(self):
return self.mapper.parser.operatorRepresentation['size']

class PerturbRademacherLayer(ONNXLayer):
def __init__(self, maps: List[NodeMapper]):
super().__init__(maps)

def computeOps(self):
return self.mapper.parser.operatorRepresentation['size']

class PerturbTriangleLayer(ONNXLayer):
def __init__(self, maps: List[NodeMapper]):
super().__init__(maps)

def computeOps(self):
return self.mapper.parser.operatorRepresentation['size']

170 changes: 169 additions & 1 deletion Deeploy/Targets/Generic/Parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,10 @@ def parseNode(self, node: gs.Node) -> (bool):

if ret:
if 'kernel_shape' not in node.attrs:
node.attrs['kernel_shape'] = node.inputs[1].shape[-2:]
if self.operatorRepresentation['channels_first']:
node.attrs['kernel_shape'] = node.inputs[1].shape[-2:]
else:
node.attrs['kernel_shape'] = node.inputs[1].shape[1:3]
self.operatorRepresentation['kernel_shape'] = node.attrs['kernel_shape']
self.operatorRepresentation['dim_kernel_x'] = int(self.operatorRepresentation['kernel_shape'][0])
self.operatorRepresentation['dim_kernel_y'] = int(self.operatorRepresentation['kernel_shape'][1])
Expand Down Expand Up @@ -2882,3 +2885,168 @@ def parseNodeCtxt(self,
self.operatorRepresentation['size'] = int(np.prod(data_in.shape))

return ctxt, True

class PerturbNormalParser(NodeParser):

def __init__(self):
super().__init__()

def parseNode(self, node: gs.Node) -> bool:

ret = all([len(node.inputs) == 1,
len(node.outputs) == 1,
'seed' in node.attrs,
'eps' in node.attrs])
return ret

def parseNodeCtxt(self,
ctxt: NetworkContext,
node: gs.Node,
channels_first: bool = True) -> Tuple[NetworkContext, bool]:

data_in = ctxt.lookup(node.inputs[0].name)
data_out = ctxt.lookup(node.outputs[0].name)
input_shape = data_in.shape
if isinstance(data_in.shape, int):
input_shape = tuple(input_shape, )
self.operatorRepresentation['data_in'] = data_in.name
self.operatorRepresentation['data_out'] = data_out.name
self.operatorRepresentation['seed'] = node.attrs['seed']
self.operatorRepresentation['size'] = np.prod(input_shape)
self.operatorRepresentation['nodeIdx'] = node.attrs['idx']
self.operatorRepresentation['eps'] = node.attrs['eps']
return ctxt, True

class PerturbUniformParser(NodeParser):

def __init__(self):
super().__init__()

def parseNode(self, node: gs.Node) -> bool:

ret = all([len(node.inputs) == 1,
len(node.outputs) == 1,
'low' in node.attrs,
'high' in node.attrs,
'seed' in node.attrs,
'eps' in node.attrs])
return ret

def parseNodeCtxt(self,
ctxt: NetworkContext,
node: gs.Node,
channels_first: bool = True) -> Tuple[NetworkContext, bool]:

data_in = ctxt.lookup(node.inputs[0].name)
data_out = ctxt.lookup(node.outputs[0].name)
input_shape = data_in.shape
if isinstance(data_in.shape, int):
input_shape = tuple(input_shape, )
self.operatorRepresentation['data_in'] = data_in.name
self.operatorRepresentation['data_out'] = data_out.name
self.operatorRepresentation['seed'] = node.attrs['seed']
self.operatorRepresentation['size'] = np.prod(input_shape)
self.operatorRepresentation['nodeIdx'] = node.attrs['idx']
self.operatorRepresentation['eps'] = node.attrs['eps']
self.operatorRepresentation['low'] = float(node.attrs['low'])
self.operatorRepresentation['high'] = float(node.attrs['high'])

return ctxt, True

class PerturbEggrollParser(NodeParser):

def __init__(self):
super().__init__()

def parseNode(self, node: gs.Node) -> bool:

ret = all([len(node.inputs) == 1,
len(node.outputs) == 1,
'seed' in node.attrs,
'eps' in node.attrs])
return ret

def parseNodeCtxt(self,
ctxt: NetworkContext,
node: gs.Node,
channels_first: bool = True) -> Tuple[NetworkContext, bool]:

data_in = ctxt.lookup(node.inputs[0].name)
data_out = ctxt.lookup(node.outputs[0].name)
input_shape = data_in.shape
if isinstance(data_in.shape, int):
input_shape = tuple(input_shape, )
self.operatorRepresentation['data_in'] = data_in.name
self.operatorRepresentation['data_out'] = data_out.name
self.operatorRepresentation['seed'] = node.attrs['seed']
self.operatorRepresentation['sizeA'] = input_shape[0]
self.operatorRepresentation['sizeB'] = np.prod(input_shape[1:])
self.operatorRepresentation['nodeIdx'] = node.attrs['idx']
self.operatorRepresentation['eps'] = node.attrs['eps']
return ctxt, True

class PerturbRademacherParser(NodeParser):

def __init__(self):
super().__init__()

def parseNode(self, node: gs.Node) -> bool:

ret = all([len(node.inputs) == 1,
len(node.outputs) == 1,
'seed' in node.attrs,
'eps' in node.attrs])
return ret

def parseNodeCtxt(self,
ctxt: NetworkContext,
node: gs.Node,
channels_first: bool = True) -> Tuple[NetworkContext, bool]:

data_in = ctxt.lookup(node.inputs[0].name)
data_out = ctxt.lookup(node.outputs[0].name)
input_shape = data_in.shape
if isinstance(data_in.shape, int):
input_shape = tuple(input_shape, )
self.operatorRepresentation['data_in'] = data_in.name
self.operatorRepresentation['data_out'] = data_out.name
self.operatorRepresentation['seed'] = node.attrs['seed']
self.operatorRepresentation['size'] = np.prod(input_shape)
self.operatorRepresentation['nodeIdx'] = node.attrs['idx']
self.operatorRepresentation['eps'] = node.attrs['eps']
return ctxt, True


class PerturbTriangleParser(NodeParser):

def __init__(self):
super().__init__()

def parseNode(self, node: gs.Node) -> bool:

ret = all([len(node.inputs) == 1,
len(node.outputs) == 1,
'seed' in node.attrs,
'eps' in node.attrs])
return ret

def parseNodeCtxt(self,
ctxt: NetworkContext,
node: gs.Node,
channels_first: bool = True) -> Tuple[NetworkContext, bool]:

data_in = ctxt.lookup(node.inputs[0].name)
data_out = ctxt.lookup(node.outputs[0].name)
input_shape = data_in.shape
if isinstance(data_in.shape, int):
input_shape = tuple(input_shape, )
self.operatorRepresentation['data_in'] = data_in.name
self.operatorRepresentation['data_out'] = data_out.name
self.operatorRepresentation['seed'] = node.attrs['seed']
self.operatorRepresentation['size'] = np.prod(input_shape)
self.operatorRepresentation['nodeIdx'] = node.attrs['idx']
self.operatorRepresentation['eps'] = node.attrs['eps']
self.operatorRepresentation['low'] = float(node.attrs['low'])
self.operatorRepresentation['high'] = float(node.attrs['high'])

return ctxt, True
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: Netw

tilerModel.addTensorDimToModel(ctxt, tensorName)

for idx, shapeDim in enumerate(_buffer.shape):
tilerModel.addConstraint(tilerModel.getTensorDimVar(tensorName = tensorName, dimIdx = idx) == shapeDim)
if isinstance(_buffer.shape, int):
tilerModel.addConstraint(tilerModel.getTensorDimVar(tensorName = tensorName, dimIdx = 0) == _buffer.shape)
else:
for idx, shapeDim in enumerate(_buffer.shape):
tilerModel.addConstraint(tilerModel.getTensorDimVar(tensorName = tensorName, dimIdx = idx) == shapeDim)

return tilerModel

Expand Down
14 changes: 14 additions & 0 deletions Deeploy/Targets/Generic/TypeCheckers.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,3 +610,17 @@ def _inferNumLevels(self, inputs: List[VariableBuffer],
def _inferSignedness(self, inputs: List[VariableBuffer],
operatorRepresentation: OperatorRepresentation) -> List[bool]:
return [True]

class PerturbZOChecker(SignPropTypeChecker):

def __init__(self, input_types: Sequence[Type[Pointer]], output_types: Sequence[Type[Pointer]]):
super().__init__(input_types, output_types)

def _inferNumLevels(self, inputs: List[VariableBuffer],
operatorRepresentation: OperatorRepresentation) -> List[int]:
return [inputs[0].nLevels]

def _inferSignedness(self, inputs: List[VariableBuffer],
operatorRepresentation: OperatorRepresentation) -> List[bool]:
return [True]

38 changes: 36 additions & 2 deletions Deeploy/Targets/PULPOpen/Bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from Deeploy.Targets.Generic.TypeCheckers import AddChecker, ConcatChecker, ConvChecker, DequantChecker, \
GatherChecker, GELUChecker, GEMMChecker, HardswishChecker, LayerNormChecker, MatMulChecker, MulChecker, \
QuantChecker, ReduceMeanChecker, ReluChecker, ReshapeChecker, RQAddChecker, RQHardswishChecker, SGDChecker, \
SliceChecker, SoftmaxChecker, SoftmaxCrossEntropyLossChecker, TransposeChecker
SliceChecker, SoftmaxChecker, SoftmaxCrossEntropyLossChecker, TransposeChecker, PerturbZOChecker
from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPClusterSynch import PULPSynchCoresPass
from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPClusterTiling import PULPClusterTiling
from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPL3Tiling import PULPL3Tiling
Expand All @@ -32,7 +32,8 @@
FloatMulTemplate, FloatReduceMeanTemplate, FloatReluTemplate, FloatSoftmaxTemplate, GEMMTemplate, \
MatrixVectorTemplate, MaxPool2DTemplate, MulTemplate, ReduceMeanTemplate, RequantShiftTemplate, ReshapeTemplate, \
RQAddTemplate, RQSiHardswishTemplate, SGDTemplate, SoftmaxCrossEntropyLossTemplate, TallGEMMTemplate, \
TransposeTemplate, UniformRequantShiftTemplate, iRMSNormTemplate, iSoftmaxTemplate
TransposeTemplate, UniformRequantShiftTemplate, iRMSNormTemplate, iSoftmaxTemplate, FloatPerturbNormalTemplate, \
FloatPerturbUniformTemplate, FloatPerturbEggrollTemplate, FloatPerturbRademacherTemplate, FloatPerturbTriangleTemplate
from Deeploy.Targets.PULPOpen.TypeCheckers import PULPConvChecker, PULPLinearChecker, PULPMaxPoolChecker, \
PULPRequantShiftChecker
from Deeploy.TilingExtension.CodeTransformationPasses.TilingVariableReplacement import TilingVariableReplacement, \
Expand Down Expand Up @@ -368,6 +369,9 @@
PULPConcatBindings = [
NodeBinding(ConcatChecker([PointerClass(type), PointerClass(type)], [PointerClass(type)]),
ConcatTemplate.referenceTemplate, ClusterTransformer) for type in IntegerDataTypes
] + [
NodeBinding(ConcatChecker([PointerClass(float_type), PointerClass(float_type)], [PointerClass(float_type)]),
ConcatTemplate.referenceTemplate, ClusterTransformer) for float_type in FloatDataTypes
]

PULPiRMSNormBindings = [
Expand Down Expand Up @@ -448,3 +452,33 @@
NodeBinding(DequantChecker([PointerClass(int32_t)], [PointerClass(float32_t)]), DequantTemplate.referenceTemplate,
ForkTransformer),
]

PULPPerturbNormalBindings = [
NodeBinding(
PerturbZOChecker([PointerClass(float32_t)], [PointerClass(float32_t)]),
FloatPerturbNormalTemplate.referenceTemplate,
ForkTransformer)]

PULPPerturbUniformBindings = [
NodeBinding(
PerturbZOChecker([PointerClass(float32_t)], [PointerClass(float32_t)]),
FloatPerturbUniformTemplate.referenceTemplate,
ForkTransformer)]

PULPPerturbEggrollBindings = [
NodeBinding(
PerturbZOChecker([PointerClass(float32_t)], [PointerClass(float32_t)]),
FloatPerturbEggrollTemplate.referenceTemplate,
ForkTransformer)]

PULPPerturbRademacherBindings = [
NodeBinding(
PerturbZOChecker([PointerClass(float32_t)], [PointerClass(float32_t)]),
FloatPerturbRademacherTemplate.referenceTemplate,
ForkTransformer)]

PULPPerturbTriangleBindings = [
NodeBinding(
PerturbZOChecker([PointerClass(float32_t)], [PointerClass(float32_t)]),
FloatPerturbTriangleTemplate.referenceTemplate,
ForkTransformer)]
Loading