Skip to content

Commit

Permalink
further simplified RowStackNode, e.g. we actually do not need m_start…
Browse files Browse the repository at this point in the history
…RowIndices[num children]
  • Loading branch information
frankseide committed Oct 14, 2015
1 parent 19e448d commit 264f3c7
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 30 deletions.
4 changes: 2 additions & 2 deletions MachineLearning/CNTKComputationNetworkLib/ComputationNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -1146,9 +1146,9 @@ namespace Microsoft { namespace MSR { namespace CNTK {

inline ComputationNodePtr Inputs(const size_t childIndex) const // TODO: rename to Input
{
#ifdef DEBUG // profile shows this is range check very expensive in release mode, skip it
#ifdef _DEBUG // profile shows this is range check very expensive in release mode, skip it
if (childIndex >= m_children.size())
InvalidArgument ("childIndex is out of range.");
LogicError("Inputs: childIndex is out of range.");
#endif
return UpCast(m_children[childIndex]);
}
Expand Down
39 changes: 11 additions & 28 deletions MachineLearning/CNTKComputationNetworkLib/LinearAlgebraNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,11 +385,8 @@ namespace Microsoft { namespace MSR { namespace CNTK {
// stacks multiple inputs on top of each other
// -----------------------------------------------------------------------

//this node is used to extract part of the input by rows as the output
// TODO: Really? RowStack indicates something different.
//it has to be continuous segments of rows since each column is treated as one sample
template<class ElemType>
class RowStackNode : public ComputationNode<ElemType> // note: not deriving from NumInputs<> like most other nodes since this one takes a variable number of inputs
class RowStackNode : public ComputationNode<ElemType> // note: not deriving from NumInputs<> like most other nodes, because this one takes a variable number of inputs
{
typedef ComputationNode<ElemType> Base; UsingComputationNodeMembersBoilerplate;
static const std::wstring TypeName() { return L"RowStack"; }
Expand All @@ -401,71 +398,57 @@ namespace Microsoft { namespace MSR { namespace CNTK {
virtual void CopyTo(const ComputationNodePtr nodeP, const std::wstring& newName, const CopyNodeFlags flags) const
{
Base::CopyTo(nodeP, newName, flags);
auto node = dynamic_pointer_cast<RowStackNode<ElemType>>(nodeP);

if (flags & CopyNodeFlags::copyNodeChildren)
{
node->m_children = m_children;
auto node = dynamic_pointer_cast<RowStackNode<ElemType>>(nodeP);
node->m_startRowIndices = m_startRowIndices;
}
}

virtual void ComputeInputPartial(const size_t inputIndex)
{
if (inputIndex >= ChildrenSize())
InvalidArgument("RowStack-ComputeInputPartial: inputIndex out of range.");
ComputeInputPartialS(Inputs(inputIndex)->GradientValues(), GradientValues(), m_startRowIndices[inputIndex], m_startRowIndices[inputIndex + 1] - m_startRowIndices[inputIndex]);
ComputeInputPartialS(Inputs(inputIndex)->GradientValues(), GradientValues(), m_startRowIndices[inputIndex]);
}

virtual void /*ComputationNode::*/ComputeInputPartial(const size_t inputIndex, const FrameRange & frameRange) override
{
Matrix<ElemType> sliceInputGrad = Inputs(inputIndex)->GradientSlice(frameRange/*TODO: delete this:*/.Check_t(GetNumParallelSequences(), m_pMBLayout));
Matrix<ElemType> sliceOutputGrad = GradientSlice(frameRange/*TODO: delete this:*/.Check_t(GetNumParallelSequences(), m_pMBLayout));

ComputeInputPartialS(sliceInputGrad, sliceOutputGrad, m_startRowIndices[inputIndex], m_startRowIndices[inputIndex+1] - m_startRowIndices[inputIndex]);
ComputeInputPartialS(sliceInputGrad, sliceOutputGrad, m_startRowIndices[inputIndex]);
}

/*TODO: merge with call site*/void ComputeInputPartialS(Matrix<ElemType>& inputGradientValues, const Matrix<ElemType>& gradientValues, const size_t startIndex, const size_t numRows)
/*TODO: merge with call site*/void ComputeInputPartialS(Matrix<ElemType>& inputGradientValues, const Matrix<ElemType>& gradientValues, const size_t startIndex)
{
inputGradientValues.AddWithRowSliceValuesOf(gradientValues, startIndex, numRows);
inputGradientValues.AddWithRowSliceValuesOf(gradientValues, startIndex, inputGradientValues.GetNumRows());
}

virtual void /*ComputationNode::*/EvaluateThisNode(const FrameRange & frameRange) override
{

#if 1 // assign as row slices, as that allows us to use the ValueSlice() function
for (size_t i = 0; i < ChildrenSize(); i++)
ValueSlice(frameRange).AssignRowSliceValuesOf(Inputs(i)->ValueSlice(frameRange), m_startRowIndices[i], Inputs(i)->GetNumRows());
#else
Matrix<ElemType> sliceFunctionValues = ValueSlice(frameRange/*TODO: delete this:*/.Check_t(GetNumParallelSequences(), m_pMBLayout));
sliceFunctionValues.AssignRowStackValuesOf(m_inputMatrices, frameRange.t() * GetNumParallelSequences(), GetNumParallelSequences());
#endif
}

virtual void /*ComputationNodeBase::*/Validate(bool isFinalValidationPass) override
{
Base::Validate(isFinalValidationPass);
InferMBLayoutFromInputsForStandardCase();

size_t numCols = Inputs(0)->GetNumCols();
m_startRowIndices.resize(ChildrenSize()+1);

// count totalRows and form m_startRowIndices[] array, which is the cumulative sum of matrix heights
m_startRowIndices.resize(ChildrenSize());
size_t totalRows = 0;
m_startRowIndices[0] = 0;

// TODO: why do we need Inputs(xxx)->FunctionValues()]? Why not operate directly on Inputs(.)->FunctionValues()?
for (int i = 0; i < ChildrenSize(); i++)
{
size_t numRows = Inputs(i)->GetNumRows();

if (isFinalValidationPass && Inputs(i)->GetNumCols() != numCols)
LogicError("RowStack operation: the input node %ls has different number of columns.", Inputs(i)->NodeName().c_str());

totalRows += numRows;
m_startRowIndices[i + 1] = m_startRowIndices[i] + numRows;
m_startRowIndices[i] = totalRows;
totalRows += Inputs(i)->GetNumRows();
}

Resize(totalRows, numCols);
InferMBLayoutFromInputsForStandardCase();
InferImageDimsFromInputs();
}

Expand Down

0 comments on commit 264f3c7

Please sign in to comment.