Commit baad6629 by xiaotong

improve the space management

parent 6ea64b51
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
namespace nts{ namespace nts{
/* compute dE/dx of a node */ /* compute dE/dx of a node */
void XFuncGrad::MakeGrad(XTensor * node) void XFuncGrad::MakeGrad(XTensor * node, bool isEfficient)
{ {
......
...@@ -35,7 +35,7 @@ class XFuncGrad ...@@ -35,7 +35,7 @@ class XFuncGrad
public: public:
/* compute dE/dx of a node */ /* compute dE/dx of a node */
static static
void MakeGrad(XTensor * node); void MakeGrad(XTensor * node, bool isEfficient);
/* indicates whether the node is for an activation function */ /* indicates whether the node is for an activation function */
static static
......
...@@ -33,7 +33,7 @@ class XMathGrad ...@@ -33,7 +33,7 @@ class XMathGrad
public: public:
/* compute dE/dx of a node */ /* compute dE/dx of a node */
static static
void MakeGrad(XTensor * node); void MakeGrad(XTensor * node, bool isEfficient);
/* indicates whether the node is for a math operation */ /* indicates whether the node is for a math operation */
static static
...@@ -43,121 +43,121 @@ private: ...@@ -43,121 +43,121 @@ private:
/* gradient for absolute */ /* gradient for absolute */
static static
void GradAbsolute(XTensor * node); void GradAbsolute(XTensor * node, bool isEfficient);
/* gradient for cos */ /* gradient for cos */
static static
void GradCos(XTensor * node); void GradCos(XTensor * node, bool isEfficient);
/* gradient for exp */ /* gradient for exp */
static static
void GradExp(XTensor * node); void GradExp(XTensor * node, bool isEfficient);
/* gradient for log: c = log(a) */ /* gradient for log: c = log(a) */
static static
void GradLog(XTensor * node); void GradLog(XTensor * node, bool isEfficient);
/* gradient for round */ /* gradient for round */
static static
void GradRound(XTensor * node); void GradRound(XTensor * node, bool isEfficient);
/* gradient for sign */ /* gradient for sign */
static static
void GradSign(XTensor * node); void GradSign(XTensor * node, bool isEfficient);
/* gradient for sin */ /* gradient for sin */
static static
void GradSin(XTensor * node); void GradSin(XTensor * node, bool isEfficient);
/* gradient for tan */ /* gradient for tan */
static static
void GradTan(XTensor * node); void GradTan(XTensor * node, bool isEfficient);
/* gradient for clip */ /* gradient for clip */
static static
void GradClip(XTensor * node); void GradClip(XTensor * node, bool isEfficient);
/* gradient for Divide */ /* gradient for Divide */
static static
void GradDiv(XTensor * node); void GradDiv(XTensor * node, bool isEfficient);
/* gradient for DivideDim */ /* gradient for DivideDim */
static static
void GradDivDim(XTensor * node); void GradDivDim(XTensor * node, bool isEfficient);
/* gradient for matrix multiply: c = matmul(a, b) * \alpha */ /* gradient for matrix multiply: c = matmul(a, b) * \alpha */
static static
void GradMatrixMul(XTensor * node); void GradMatrixMul(XTensor * node, bool isEfficient);
/* gradient for matrix multiply: c = matmul(a, b) * \alpha */ /* gradient for matrix multiply: c = matmul(a, b) * \alpha */
static static
void GradMatrixMul(XTensor * a, XTensor * deda, MATRIX_TRANS_TYPE transA, void GradMatrixMul(XTensor * a, XTensor * deda, MATRIX_TRANS_TYPE transA,
XTensor * b, XTensor * dedb, MATRIX_TRANS_TYPE transB, XTensor * b, XTensor * dedb, MATRIX_TRANS_TYPE transB,
XTensor * dedc, DTYPE alpha); XTensor * dedc, DTYPE alpha, bool isEfficient);
/* gradient for matrix multiply in batch mode. /* gradient for matrix multiply in batch mode.
for each batch: c_i = matmul(a_i, b_i) * \alpha */ for each batch: c_i = matmul(a_i, b_i) * \alpha */
static static
void GradMatrixMulBatched(XTensor * node); void GradMatrixMulBatched(XTensor * node, bool isEfficient);
/* gradient for multiply (dot production): c = a * b * \alpha */ /* gradient for multiply (dot production): c = a * b * \alpha */
static static
void GradMultiply(XTensor * node); void GradMultiply(XTensor * node, bool isEfficient);
/* gradient for multiply one dimension: c = a * b * \alpha /* gradient for multiply one dimension: c = a * b * \alpha
where the size of b is equal to that of one dimension of a */ where the size of b is equal to that of one dimension of a */
static static
void GradMultiplyDim(XTensor * node); void GradMultiplyDim(XTensor * node, bool isEfficient);
/* gradient for negate */ /* gradient for negate */
static static
void GradNegate(XTensor * node); void GradNegate(XTensor * node, bool isEfficient);
/* gradient for normalize */ /* gradient for normalize */
static static
void GradNormalize(XTensor * node); void GradNormalize(XTensor * node, bool isEfficient);
/* gradient for power */ /* gradient for power */
static static
void GradPower(XTensor * node); void GradPower(XTensor * node, bool isEfficient);
/* gradient for ScaleAndShift */ /* gradient for ScaleAndShift */
static static
void GradScaleAndShift(XTensor * node); void GradScaleAndShift(XTensor * node, bool isEfficient);
/* gradient for Minus */ /* gradient for Minus */
static static
void GradSub(XTensor * node); void GradSub(XTensor * node, bool isEfficient);
/* gradient for sub with one dimension: c = a - b * \beta /* gradient for sub with one dimension: c = a - b * \beta
where the size of b is equal to that of one dimension of a */ where the size of b is equal to that of one dimension of a */
static static
void GradSubDim(XTensor * node); void GradSubDim(XTensor * node, bool isEfficient);
/* gradient for sum: c = a + b * \beta */ /* gradient for sum: c = a + b * \beta */
static static
void GradSum(XTensor * node); void GradSum(XTensor * node, bool isEfficient);
/* gradient for sum with one dimension: c = a + b * \beta /* gradient for sum with one dimension: c = a + b * \beta
where the size of b is equal to that of one dimension of a */ where the size of b is equal to that of one dimension of a */
static static
void GradSumDim(XTensor * node); void GradSumDim(XTensor * node, bool isEfficient);
/* gradient for reduceMean */ /* gradient for reduceMean */
static static
void GradReduceMean(XTensor * node); void GradReduceMean(XTensor * node, bool isEfficient);
/* gradient for reduceSum */ /* gradient for reduceSum */
static static
void GradReduceSum(XTensor * node); void GradReduceSum(XTensor * node, bool isEfficient);
/* gradient for reduceSumSquared */ /* gradient for reduceSumSquared */
static static
void GradReduceSumSquared(XTensor * node); void GradReduceSumSquared(XTensor * node, bool isEfficient);
/* gradient for reduceVariance */ /* gradient for reduceVariance */
static static
void GradReduceVariance(XTensor * node); void GradReduceVariance(XTensor * node, bool isEfficient);
}; };
} }
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
namespace nts{ namespace nts{
/* compute dE/dx of a node */ /* compute dE/dx of a node */
void XShapeGrad::MakeGrad(XTensor * node) void XShapeGrad::MakeGrad(XTensor * node, bool isEfficent)
{ {
CheckNTErrors(node->grad != NULL, "No gradient found!"); CheckNTErrors(node->grad != NULL, "No gradient found!");
...@@ -38,17 +38,17 @@ void XShapeGrad::MakeGrad(XTensor * node) ...@@ -38,17 +38,17 @@ void XShapeGrad::MakeGrad(XTensor * node)
int operID = income.typeID; int operID = income.typeID;
if(operID == SHAPE_MERGE) if(operID == SHAPE_MERGE)
GradMerge(node); GradMerge(node, isEfficent);
else if(operID == SHAPE_MERGE_LIST) else if(operID == SHAPE_MERGE_LIST)
GradMergeList(node); GradMergeList(node, isEfficent);
else if(operID == SHAPE_UNSQUEEZE) else if(operID == SHAPE_UNSQUEEZE)
GradUnsqueeze(node); GradUnsqueeze(node, isEfficent);
else if(operID == SHAPE_SPLIT) else if(operID == SHAPE_SPLIT)
GradSplit(node); GradSplit(node, isEfficent);
else if(operID == SHAPE_SPLIT_LIST) else if(operID == SHAPE_SPLIT_LIST)
GradSplitList(node); GradSplitList(node, isEfficent);
else if (operID == SHAPE_TRANSPOSE) else if (operID == SHAPE_TRANSPOSE)
GradTranspose(node); GradTranspose(node, isEfficent);
else{ else{
ShowNTErrors("TODO!"); ShowNTErrors("TODO!");
} }
...@@ -62,10 +62,10 @@ bool XShapeGrad::IsShapeOP(XTensor * node) ...@@ -62,10 +62,10 @@ bool XShapeGrad::IsShapeOP(XTensor * node)
} }
/* post processing of a node */ /* post processing of a node */
void XShapeGrad::PostProcessing(XTensor * node, int typeID) void XShapeGrad::PostProcessing(XTensor * node, int typeID, bool isEfficent)
{ {
if(typeID == SHAPE_SPLIT_LIST) if(typeID == SHAPE_SPLIT_LIST)
GradSplitListPost(node); GradSplitListPost(node, isEfficent);
} }
/* /*
...@@ -80,8 +80,10 @@ dE/db_1 = dE/dc_{split_1} ...@@ -80,8 +80,10 @@ dE/db_1 = dE/dc_{split_1}
i.e., i.e.,
dE/da = split(dE/dc) dE/da = split(dE/dc)
>> node - the node (c) for backward computation >> node - the node (c) for backward computation
>> isEfficient - indicates whether the computation is in
an efficient manner
*/ */
void XShapeGrad::GradMerge(XTensor * node) void XShapeGrad::GradMerge(XTensor * node, bool isEfficent)
{ {
XLink &income = node->income; XLink &income = node->income;
XTensor * input = income.tails[0]; XTensor * input = income.tails[0];
...@@ -162,8 +164,10 @@ dE/db = dE/dc_{split_1} ...@@ -162,8 +164,10 @@ dE/db = dE/dc_{split_1}
i.e., i.e.,
list(dE/da, dE/db, ...) = split(dE/dc) list(dE/da, dE/db, ...) = split(dE/dc)
>> node - the node (c) for backward computation >> node - the node (c) for backward computation
>> isEfficient - indicates whether the computation is in
an efficient manner
*/ */
void XShapeGrad::GradMergeList(XTensor * node) void XShapeGrad::GradMergeList(XTensor * node, bool isEfficient)
{ {
XLink &income = node->income; XLink &income = node->income;
CheckNTErrors(income.tailNum > 0, "Wrong input tensor number for MERGE!"); CheckNTErrors(income.tailNum > 0, "Wrong input tensor number for MERGE!");
...@@ -239,8 +243,10 @@ c = split(a) ...@@ -239,8 +243,10 @@ c = split(a)
we have we have
dE/da = merge(dE/dc) dE/da = merge(dE/dc)
>> node - the node (c) for backward computation >> node - the node (c) for backward computation
>> isEfficient - indicates whether the computation is in
an efficient manner
*/ */
void XShapeGrad::GradSplit(XTensor * node) void XShapeGrad::GradSplit(XTensor * node, bool isEfficient)
{ {
XLink &income = node->income; XLink &income = node->income;
XTensor * input = income.tails[0]; XTensor * input = income.tails[0];
...@@ -279,8 +285,10 @@ list(c_1, ...) = split(a) ...@@ -279,8 +285,10 @@ list(c_1, ...) = split(a)
we have we have
dE/da = merge(dE/c_1, ...) dE/da = merge(dE/c_1, ...)
>> node - the node (c) for backward computation >> node - the node (c) for backward computation
>> isEfficient - indicates whether the computation is in
an efficient manner
*/ */
void XShapeGrad::GradSplitList(XTensor * node) void XShapeGrad::GradSplitList(XTensor * node, bool isEfficient)
{ {
XLink &income = node->income; XLink &income = node->income;
XTensor * input = income.tails[0]; XTensor * input = income.tails[0];
...@@ -299,8 +307,10 @@ have been processed. We do this in a post-processing ...@@ -299,8 +307,10 @@ have been processed. We do this in a post-processing
manner because we can fuze multiple memory copy jobs manner because we can fuze multiple memory copy jobs
one time. This is good for system speed up. one time. This is good for system speed up.
>> node - the node (c) for backward computation >> node - the node (c) for backward computation
>> isEfficient - indicates whether the computation is in
an efficient manner
*/ */
void XShapeGrad::GradSplitListPost(XTensor * node) void XShapeGrad::GradSplitListPost(XTensor * node, bool isEfficient)
{ {
/* we compute the gradient for current node, rather than for /* we compute the gradient for current node, rather than for
child node, i.e., we use the outgoing edge here */ child node, i.e., we use the outgoing edge here */
...@@ -351,8 +361,10 @@ c = unsqueeze(a) ...@@ -351,8 +361,10 @@ c = unsqueeze(a)
we have we have
dE/da = reduecesum(dE/dc) dE/da = reduecesum(dE/dc)
>> node - the node (c) for backward computation >> node - the node (c) for backward computation
>> isEfficient - indicates whether the computation is in
an efficient manner
*/ */
void XShapeGrad::GradUnsqueeze(XTensor * node) void XShapeGrad::GradUnsqueeze(XTensor * node, bool isEfficient)
{ {
XLink &income = node->income; XLink &income = node->income;
CheckNTErrors(income.tailNum == 1, "Wrong input tensor number for UNSQUEEZE!"); CheckNTErrors(income.tailNum == 1, "Wrong input tensor number for UNSQUEEZE!");
...@@ -379,8 +391,10 @@ c = Transpose(a) ...@@ -379,8 +391,10 @@ c = Transpose(a)
we have we have
dE/da = Transpose(dE/dc) dE/da = Transpose(dE/dc)
>> node - the node (c) for backward computation >> node - the node (c) for backward computation
>> isEfficient - indicates whether the computation is in
an efficient manner
*/ */
void XShapeGrad::GradTranspose(XTensor * node) void XShapeGrad::GradTranspose(XTensor * node, bool isEfficient)
{ {
XLink &income = node->income; XLink &income = node->income;
CheckNTErrors(income.tailNum == 1, "Wrong input tensor number for TRANSPOSE!"); CheckNTErrors(income.tailNum == 1, "Wrong input tensor number for TRANSPOSE!");
......
...@@ -34,7 +34,7 @@ class XShapeGrad ...@@ -34,7 +34,7 @@ class XShapeGrad
public: public:
/* compute dE/dx of a node */ /* compute dE/dx of a node */
static static
void MakeGrad(XTensor * node); void MakeGrad(XTensor * node, bool isEfficent);
/* indicates whether the node is for a shaping operation */ /* indicates whether the node is for a shaping operation */
static static
...@@ -42,38 +42,38 @@ public: ...@@ -42,38 +42,38 @@ public:
/* post processing of a node */ /* post processing of a node */
static static
void PostProcessing(XTensor * node, int typeId); void PostProcessing(XTensor * node, int typeId, bool isEfficent);
private: private:
/* gradient computation for merge: c = merge(a, b, ...) */ /* gradient computation for merge: c = merge(a, b, ...) */
static static
void GradMerge(XTensor * node); void GradMerge(XTensor * node, bool isEfficent);
/* gradient computation for merging a list of tensors : c = merge(list(a, b, ...)) */ /* gradient computation for merging a list of tensors : c = merge(list(a, b, ...)) */
static static
void GradMergeList(XTensor * node); void GradMergeList(XTensor * node, bool isEfficent);
/* gradient computation for split: c = split(a) */ /* gradient computation for split: c = split(a) */
static static
void GradSplit(XTensor * node); void GradSplit(XTensor * node, bool isEfficent);
/* gradient computation for spliting. we return the list of the splits : list(c_1, ...) = split(a) */ /* gradient computation for spliting. we return the list of the splits : list(c_1, ...) = split(a) */
static static
void GradSplitList(XTensor * node); void GradSplitList(XTensor * node, bool isEfficent);
/* gradient computation for spliting. we return the list of the splits : list(c_1, ...) = split(a). /* gradient computation for spliting. we return the list of the splits : list(c_1, ...) = split(a).
this method is called only when all nodes of spliting have been processed. We do this in a post-processing this method is called only when all nodes of spliting have been processed. We do this in a post-processing
manner because we can fuze multiple memory copy jobs one time. This is good for system speed up. */ manner because we can fuze multiple memory copy jobs one time. This is good for system speed up. */
static static
void GradSplitListPost(XTensor * node); void GradSplitListPost(XTensor * node, bool isEfficent);
/* gradient computation for unsqueezing a tensor : c = unsqueeze(a) */ /* gradient computation for unsqueezing a tensor : c = unsqueeze(a) */
static static
void GradUnsqueeze(XTensor * node); void GradUnsqueeze(XTensor * node, bool isEfficent);
/* gradient computation for unsqueezing a tensor : c = unsqueeze(a) */ /* gradient computation for unsqueezing a tensor : c = unsqueeze(a) */
static static
void GradTranspose(XTensor * node); void GradTranspose(XTensor * node, bool isEfficent);
}; };
......
...@@ -55,6 +55,7 @@ void XNetClearAll() ...@@ -55,6 +55,7 @@ void XNetClearAll()
XNet::XNet() XNet::XNet()
{ {
nodes.Clear(); nodes.Clear();
isGradEfficient = false;
} }
/* de-constructor */ /* de-constructor */
...@@ -115,6 +116,10 @@ void XNet::Backward(XList &roots, XList &golds, LOSS_FUNCTION_NAME loss) ...@@ -115,6 +116,10 @@ void XNet::Backward(XList &roots, XList &golds, LOSS_FUNCTION_NAME loss)
{ {
Traverse(roots); Traverse(roots);
/* label tensors where the backward computation is neccessary */
if(isGradEfficient)
MakeEfficientNet();
for(int i = 0; i < nodes.count; i++){ for(int i = 0; i < nodes.count; i++){
XTensor * node = (XTensor*)nodes.Get(i); XTensor * node = (XTensor*)nodes.Get(i);
node->visitMark = NODE_UNFINISHED; node->visitMark = NODE_UNFINISHED;
...@@ -154,10 +159,20 @@ void XNet::Backward(XList &roots, XList &golds, LOSS_FUNCTION_NAME loss) ...@@ -154,10 +159,20 @@ void XNet::Backward(XList &roots, XList &golds, LOSS_FUNCTION_NAME loss)
CheckNTErrors(node->mem->bufUsed < BUF_PITCH, "Illegal access of buffer!"); CheckNTErrors(node->mem->bufUsed < BUF_PITCH, "Illegal access of buffer!");
} }
if(node->visitMark == NODE_FINISHED) if(node->visitMark != NODE_FINISHED)
continue; BackwardNode(node, isGradEfficient);
BackwardNode(node); if(isGradEfficient){
if(!XNoder::IsLeaf(node)){
XLink & outgo = node->outgo;
for(int i = 0; i < outgo.tailNum; i++){
XTensor * parent = outgo.tails[i];
ClearGrad(parent);
}
}
else
ClearGrad(node);
}
} }
} }
...@@ -179,27 +194,32 @@ void XNet::Backward(XList &roots, LOSS_FUNCTION_NAME loss) ...@@ -179,27 +194,32 @@ void XNet::Backward(XList &roots, LOSS_FUNCTION_NAME loss)
/* /*
backward computation for a given node backward computation for a given node
>> node - the node keeps the result of an operation (e.g., activation function) >> node - the node keeps the result of an operation (e.g., activation function)
>> isEfficient - indicates whether the back-propagation is compuated in an
efficient manner
*/ */
void XNet::BackwardNode(XTensor * node) void XNet::BackwardNode(XTensor * node, bool isEfficent)
{ {
if(node == NULL || node->visitMark == NODE_FINISHED) if(node == NULL || node->visitMark == NODE_FINISHED)
return; return;
if(!XNoder::IsLeaf(node)){ if(!XNoder::IsLeaf(node)){
/* post processing for parent nodes */ /* post processing for parent nodes */
BackwardNodePost(node); BackwardNodePost(node, isEfficent);
/* process the current node */ /* process the current node */
if(XMathGrad::IsMathOP(node)) if(XMathGrad::IsMathOP(node))
XMathGrad::MakeGrad(node); XMathGrad::MakeGrad(node, isEfficent);
else if(XFuncGrad::IsFunc(node)) else if(XFuncGrad::IsFunc(node))
XFuncGrad::MakeGrad(node); XFuncGrad::MakeGrad(node, isEfficent);
else if(XShapeGrad::IsShapeOP(node)) else if(XShapeGrad::IsShapeOP(node))
XShapeGrad::MakeGrad(node); XShapeGrad::MakeGrad(node, isEfficent);
else{ else{
ShowNTErrors("Wrong node type!"); ShowNTErrors("Wrong node type!");
} }
} }
else{
node->visitMark = NODE_FINISHED;
}
} }
/* /*
...@@ -207,7 +227,7 @@ backward computation (in post processing) for a given node ...@@ -207,7 +227,7 @@ backward computation (in post processing) for a given node
>> node - the node whose parent nodes are not processed yet. So >> node - the node whose parent nodes are not processed yet. So
we do the job at the child node. we do the job at the child node.
*/ */
void XNet::BackwardNodePost(XTensor * node) void XNet::BackwardNodePost(XTensor * node, bool isEfficent)
{ {
bool isSplitList = false; bool isSplitList = false;
XLink &outgo = node->outgo; XLink &outgo = node->outgo;
...@@ -217,7 +237,7 @@ void XNet::BackwardNodePost(XTensor * node) ...@@ -217,7 +237,7 @@ void XNet::BackwardNodePost(XTensor * node)
} }
if(isSplitList) if(isSplitList)
XShapeGrad::PostProcessing(node, SHAPE_SPLIT_LIST); XShapeGrad::PostProcessing(node, SHAPE_SPLIT_LIST, isEfficent);
} }
/* /*
...@@ -304,4 +324,62 @@ void XNet::Dump(FILE * file) ...@@ -304,4 +324,62 @@ void XNet::Dump(FILE * file)
} }
} }
/*
set the flag of gradient-efficient
>> flag - the flag
*/
void XNet::SetGradEfficientFlag(bool flag)
{
isGradEfficient = flag;
}
/* generate the gradient-efficient flag for every node */
void XNet::MakeEfficientNet()
{
/* back-propagation from output to input */
for(int i = 0; i < nodes.count; i++){
XTensor * node = (XTensor*)nodes.Get(i);
XLink &income = node->income;
for(int j = 0; j < income.tailNum; j++){
XTensor * child = income.tails[j];
if(child->isGrad || child->isVar){
node->SetGradFlag(true);
break;
}
}
}
}
/*
clear the graident information if the node is no use
>> node - the node that we want to clear
*/
void XNet::ClearGrad(XTensor * node)
{
if(node->isVar)
return;
if(node->grad == NULL)
return;
if(node->visitMark != NODE_FINISHED)
return;
XLink & income = node->income;
bool finished = true;
for(int i = 0; i < income.tailNum; i++){
XTensor * child = income.tails[i];
if(child->visitMark != NODE_FINISHED){
finished = false;
break;
}
}
if(finished){
//fprintf(stderr, "del %d %ld\n", node->id, node->grad->unitNum);
delete node->grad;
node->grad = NULL;
}
}
} }
\ No newline at end of file
...@@ -47,6 +47,9 @@ struct XNet ...@@ -47,6 +47,9 @@ struct XNet
/* input nodes of the network */ /* input nodes of the network */
XList inputs; XList inputs;
/* indicates whether the network just keeps the gradient for parameter tensors */
bool isGradEfficient;
/* constructor */ /* constructor */
XNet(); XNet();
...@@ -71,10 +74,10 @@ struct XNet ...@@ -71,10 +74,10 @@ struct XNet
void Backward(XList &roots, LOSS_FUNCTION_NAME loss = NOLOSS); void Backward(XList &roots, LOSS_FUNCTION_NAME loss = NOLOSS);
/* backward computation for a given node */ /* backward computation for a given node */
void BackwardNode(XTensor * node); void BackwardNode(XTensor * node, bool isEfficent = false);
/* backward computation (in post processing) for a given node */ /* backward computation (in post processing) for a given node */
void BackwardNodePost(XTensor * node); void BackwardNodePost(XTensor * node, bool isEfficent = false);
/* traverse the net and find the topological order by /* traverse the net and find the topological order by
depth-first search (Tarjan's algorithm) */ depth-first search (Tarjan's algorithm) */
...@@ -89,6 +92,15 @@ struct XNet ...@@ -89,6 +92,15 @@ struct XNet
/* dump network information */ /* dump network information */
void Dump(FILE * file); void Dump(FILE * file);
/* set the flag of gradient-efficient */
void SetGradEfficientFlag(bool flag = true);
/* generate the gradient-efficient flag for every node */
void MakeEfficientNet();
/* clear the graident information if the node is no use */
void ClearGrad(XTensor * node);
}; };
/* we make a unique id for every tensor */ /* we make a unique id for every tensor */
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论