All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ComputationStepsComputer Class Reference

This class arranges the cindex_ids of the computation into a sequence of lists called "steps", which will correspond roughly to the commands in the compiled computation. More...

#include <nnet-computation-graph.h>

Collaboration diagram for ComputationStepsComputer:

Public Member Functions

 ComputationStepsComputer (const Nnet &nnet, ComputationGraph *graph, std::vector< std::vector< int32 > > *steps, std::vector< std::pair< int32, int32 > > *locations)
 Constructor. More...
 
void ComputeForSegment (const ComputationRequest &request, const std::vector< std::vector< int32 > > &phases)
 You call this once for each segment, in order (note: for normal, non-online computations, there is only one segment). More...
 
void Check () const
 This is only to be called after you have called ComputeForSegment for all the segments. More...
 

Private Member Functions

void ProcessSubPhase (const ComputationRequest &request, const std::vector< Cindex > &sub_phase)
 
void ProcessDimRangeSubPhase (const std::vector< Cindex > &sub_phase)
 
void ProcessInputOrOutputStep (const ComputationRequest &request, bool is_output, const std::vector< Cindex > &sub_phase)
 
void ProcessComponentStep (const std::vector< Cindex > &step)
 
void SplitIntoSubPhases (const std::vector< int32 > &phase, std::vector< std::vector< Cindex > > *sub_phase) const
 
int32 AddStep (const std::vector< Cindex > &cindexes, bool add_if_absent=false)
 
int32 AddStep (std::vector< int32 > *cindex_ids)
 
void ConvertToCindexes (const std::vector< int32 > &cindex_ids, std::vector< Cindex > *cindexes) const
 
void ConvertToCindexIds (const std::vector< Cindex > &cindexes, std::vector< int32 > *cindex_ids) const
 
void ConvertToLocations (const std::vector< int32 > &cindex_ids, std::vector< std::pair< int32, int32 > > *locations) const
 

Static Private Member Functions

static void ConvertToIndexes (const std::vector< Cindex > &cindexes, std::vector< Index > *indexes)
 
static void ConvertToCindexes (const std::vector< Index > &indexes, int32 node_index, std::vector< Cindex > *cindexes)
 

Private Attributes

const Nnetnnet_
 
ComputationGraphgraph_
 
std::vector< std::vector
< int32 > > * 
steps_
 steps_ is a pointer to an output that's passed in in the constructor. More...
 
std::vector< std::pair< int32,
int32 > > * 
locations_
 locations_ is a map from cindex_id to the pair of indexes into steps_ where that cindex_id resides, so if (*locations_)[c] = (i,j), then (*steps_)[i][j] == c. More...
 

Detailed Description

This class arranges the cindex_ids of the computation into a sequence of lists called "steps", which will correspond roughly to the commands in the compiled computation.

The steps are finer than phases. (See Organizing the computation into steps for more info). To summarize the properties that these steps will satisfy:

  • All cindex_ids within a given step correspond to the same node in the graph
  • All dependencies of cindex_ids within a given step have been computed in earlier steps.
  • All cindex_ids within a given step share the same location when computed (i.e. a matrix or submatix)

There are also some extra, more obscure properties that the sequence of steps must satisfy:

  • Any input or output specified in a ComputationRequest must be in one step, with the Indexes in the same order as specified in the ComputationRequest. (Note: inputs can be for nodes of type kComponent as well as kInput).
  • If a step corresponds to a node of type kComponent (and does not correspond to an input in the ComputationRequest), then the immediately preceding step must correspond to a node of type kDescriptor, and the sequence of Indexes in the two steps must be identical.
  • If a step corresponds to a node of type kDimRange, then there must be a preceding step corresponding to the source node, with exactly the same Indexes appearing in the same order. (This lets us use a sub-matrix for the kDimRange node). We guarantee this by adding extra cindexes to the kDimRange steps as needed.

The reason why computation_graph is not provided as a const argument is that in order to ensure the final property we may have to add a few new cindex_ids.

Definition at line 414 of file nnet-computation-graph.h.

Constructor & Destructor Documentation

ComputationStepsComputer ( const Nnet nnet,
ComputationGraph graph,
std::vector< std::vector< int32 > > *  steps,
std::vector< std::pair< int32, int32 > > *  locations 
)

Constructor.

Parameters
[in]nnetThe neural network that this computation is for.
[in,out]graphThe computation graph that we're computing the steps for. It's only non-const because there are couple of unusual situations in which we may need to add new cindexes: (1) For nodes of type kDimRange, we may add cindexes to enable the node to span a contiguous range of the input indexes. (2) For certain non-simple Components (principally CNN-related components), we may need to add 'blank' cindexes (defined as cindexes where the 't' indexes are replaced by kNoTime), for zero-padding and to turn irregularly structured computations into regularly structured ones as needed by the component's implementation.
[out]stepsThe main output of this class, which is a sequence of steps, each step being an ordered list of cindex_ids. It just gets cleared in the constructor; it's set up when you call ComputeForSegment().
[out]locationsThe additional output of this class, which is a function of the information in 'steps'. The array 'locations' is indexed by cindex_id, and each one is a pair (step-index, index-into-step), so that for any cindex_id c, (*steps)[locations[c].first][locations[c].second] == c. It's possible in principle if there are non-simple Components, that for node corresponding to component-input descriptors, a cindex might be present in more than one step, so it doesn't follow that if (*steps)[i][j] == c, then locations[c] == (i,j).

Definition at line 1539 of file nnet-computation-graph.cc.

References ComputationGraph::cindexes, ComputationStepsComputer::graph_, ComputationStepsComputer::locations_, and ComputationStepsComputer::steps_.

1543  :
1544  nnet_(nnet), graph_(graph), steps_(steps), locations_(locations) {
1545  steps_->clear();
1546  locations_->clear();
1547  int32 num_cindexes = graph_->cindexes.size();
1548  // leave a little space in case a few cindexes are added (unlikely
1549  // but could happen with dim-range nodes).
1550  locations_->reserve(num_cindexes + num_cindexes / 10);
1551  locations_->resize(num_cindexes, std::pair<int32,int32>(-1, -1));
1552 }
std::vector< std::pair< int32, int32 > > * locations_
locations_ is a map from cindex_id to the pair of indexes into steps_ where that cindex_id resides...
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
std::vector< std::vector< int32 > > * steps_
steps_ is a pointer to an output that's passed in in the constructor.

Member Function Documentation

int32 AddStep ( const std::vector< Cindex > &  cindexes,
bool  add_if_absent = false 
)
private

Definition at line 1607 of file nnet-computation-graph.cc.

References ComputationGraph::GetCindexId(), ComputationStepsComputer::graph_, KALDI_ASSERT, ComputationStepsComputer::locations_, and ComputationStepsComputer::steps_.

Referenced by ComputationStepsComputer::ProcessComponentStep(), ComputationStepsComputer::ProcessDimRangeSubPhase(), and ComputationStepsComputer::ProcessInputOrOutputStep().

1608  {
1609  // note: we can't assert that cindexes is nonempty, because it's possible for
1610  // input steps for GeneralComponents to be empty if they require no input
1611  // indexes; and because the compiler code expects component steps to be
1612  // preceded by component-input steps, we can't just omit these empty steps.
1613  // [note: a component-input step is about preparing the input for a component's
1614  // propagation.]
1615  int32 step_index = steps_->size();
1616  steps_->push_back(std::vector<int32>());
1617  std::vector<int32> &step = steps_->back(); // vector of cindex_id.
1618  step.resize(cindexes.size());
1619  size_t row_index = 0;
1620  std::vector<Cindex>::const_iterator iter = cindexes.begin(),
1621  end = cindexes.end();
1622  std::vector<int32>::iterator out_iter = step.begin();
1623  std::pair<int32, int32> *locations = &((*locations_)[0]);
1624  if (!add_if_absent) {
1625  // this version of GetCindexId will not add CindexIds, and
1626  // will crash if CindexIds not present in the graph are
1627  // encountered.
1628  for (; iter != end; ++iter, ++out_iter, ++row_index) {
1629  int32 cindex_id = graph_->GetCindexId(*iter);
1630  *out_iter = cindex_id;
1631  locations[cindex_id].first = step_index;
1632  locations[cindex_id].second = row_index;
1633  }
1634  } else {
1635  for (; iter != end; ++iter, ++out_iter, ++row_index) {
1636  bool is_input = false; // only relevant if we have to add the cindex to
1637  // the computation graph, which we won't for
1638  // inputs (we only might for dim-range nodes
1639  // and for the component-input and component
1640  // steps of non-simple Components.
1641  bool added;
1642  int32 cindex_id = graph_->GetCindexId(*iter, is_input, &added);
1643  *out_iter = cindex_id;
1644  if (added) {
1645  KALDI_ASSERT(cindex_id == static_cast<int32>(locations_->size()));
1646  locations_->resize(cindex_id + 1);
1647  locations_->back().first = step_index;
1648  locations_->back().second = row_index;
1649  locations = &((*locations_)[0]); // in case it was reallocated
1650  } else {
1651  locations[cindex_id].first = step_index;
1652  locations[cindex_id].second = row_index;
1653  }
1654  }
1655  }
1656  return step_index;
1657 }
std::vector< std::pair< int32, int32 > > * locations_
locations_ is a map from cindex_id to the pair of indexes into steps_ where that cindex_id resides...
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
std::vector< std::vector< int32 > > * steps_
steps_ is a pointer to an output that's passed in in the constructor.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
int32 AddStep ( std::vector< int32 > *  cindex_ids)
private

Definition at line 1660 of file nnet-computation-graph.cc.

References ComputationGraph::cindexes, ComputationStepsComputer::graph_, KALDI_ASSERT, and ComputationStepsComputer::steps_.

1660  {
1661  int32 step_index = steps_->size();
1662  steps_->push_back(std::vector<int32>());
1663  steps_->back().swap(*cindex_ids);
1664  std::vector<int32>::const_iterator iter = steps_->back().begin(),
1665  end = steps_->back().end();
1666  int32 row_index = 0;
1667  std::pair<int32,int32> *locations = &((*locations_)[0]);
1668  size_t num_cindexes = graph_->cindexes.size();
1669  for (; iter != end; ++iter, ++row_index) {
1670  int32 cindex_id = *iter;
1671  KALDI_ASSERT(static_cast<size_t>(cindex_id) < num_cindexes);
1672  locations[cindex_id].first = step_index;
1673  locations[cindex_id].second = row_index;
1674  }
1675  return step_index;
1676 }
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
std::vector< std::vector< int32 > > * steps_
steps_ is a pointer to an output that's passed in in the constructor.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void Check ( ) const

This is only to be called after you have called ComputeForSegment for all the segments.

Definition at line 1962 of file nnet-computation-graph.cc.

References ComputationGraph::cindexes, ComputationStepsComputer::graph_, KALDI_ASSERT, KALDI_ERR, kaldi::nnet3::kNoTime, ComputationStepsComputer::locations_, and ComputationStepsComputer::steps_.

Referenced by Compiler::CreateComputation().

1962  {
1963  int32 num_cindexes = graph_->cindexes.size();
1964  KALDI_ASSERT(locations_->size() == num_cindexes);
1965  for (int32 c = 0; c < num_cindexes; c++) {
1966  int32 step = (*locations_)[c].first,
1967  row = (*locations_)[c].second;
1968  if (!(step >= 0 && row >= 0 && (*steps_)[step][row] == c)) {
1969  // normally the 'locations' of cindexes should be unique, so we should
1970  // never normally reach this point; but it's not an error to have
1971  // duplicates of the cindexes used for 'padding' by the ReorderIndexes()
1972  // function of non-simple Components. So we check whether that's the case
1973  // before we die.
1974  if (graph_->cindexes[c].second.t != kNoTime) {
1975  // if this happens it will likely require some debugging by Dan.
1976  KALDI_ERR << "Error in computing computation steps (likely code error)";
1977  }
1978  }
1979 
1980  }
1981 }
std::vector< std::pair< int32, int32 > > * locations_
locations_ is a map from cindex_id to the pair of indexes into steps_ where that cindex_id resides...
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
std::vector< std::vector< int32 > > * steps_
steps_ is a pointer to an output that's passed in in the constructor.
#define KALDI_ERR
Definition: kaldi-error.h:127
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
const int kNoTime
Definition: nnet-common.cc:554
void ComputeForSegment ( const ComputationRequest request,
const std::vector< std::vector< int32 > > &  phases 
)

You call this once for each segment, in order (note: for normal, non-online computations, there is only one segment).

Definition at line 1554 of file nnet-computation-graph.cc.

References rnnlm::i, rnnlm::j, ComputationStepsComputer::ProcessSubPhase(), and ComputationStepsComputer::SplitIntoSubPhases().

Referenced by Compiler::CreateComputation().

1556  {
1557  int32 this_num_phases = phases.size();
1558  for (int32 i = 0; i < this_num_phases; i++) {
1559  std::vector<std::vector<Cindex> > sub_phases;
1560  SplitIntoSubPhases(phases[i], &sub_phases);
1561  for (size_t j = 0; j < sub_phases.size(); j++) {
1562  ProcessSubPhase(request, sub_phases[j]);
1563  }
1564  }
1565 }
void SplitIntoSubPhases(const std::vector< int32 > &phase, std::vector< std::vector< Cindex > > *sub_phase) const
void ProcessSubPhase(const ComputationRequest &request, const std::vector< Cindex > &sub_phase)
void ConvertToCindexes ( const std::vector< int32 > &  cindex_ids,
std::vector< Cindex > *  cindexes 
) const
private

Definition at line 1679 of file nnet-computation-graph.cc.

References ComputationGraph::cindexes, ComputationStepsComputer::graph_, and KALDI_ASSERT.

Referenced by ComputationStepsComputer::ProcessComponentStep(), ComputationStepsComputer::ProcessDimRangeSubPhase(), and ComputationStepsComputer::SplitIntoSubPhases().

1681  {
1682  cindexes->resize(cindex_ids.size());
1683  size_t num_cindexes = graph_->cindexes.size();
1684  std::vector<int32>::const_iterator iter = cindex_ids.begin(),
1685  end = cindex_ids.end();
1686  std::vector<Cindex>::iterator out_iter = cindexes->begin();
1687  for (; iter != end; ++iter, ++out_iter) {
1688  int32 cindex_id = *iter;
1689  KALDI_ASSERT(static_cast<size_t>(cindex_id) < num_cindexes);
1690  *out_iter = graph_->cindexes[cindex_id];
1691  }
1692 }
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void ConvertToCindexes ( const std::vector< Index > &  indexes,
int32  node_index,
std::vector< Cindex > *  cindexes 
)
staticprivate

Definition at line 1723 of file nnet-computation-graph.cc.

References KALDI_ASSERT.

1726  {
1727  KALDI_ASSERT(node_index >= 0);
1728  cindexes->resize(indexes.size());
1729  std::vector<Index>::const_iterator iter = indexes.begin(),
1730  end = indexes.end();
1731  std::vector<Cindex>::iterator out_iter = cindexes->begin();
1732  for (; iter != end; ++iter, ++out_iter) {
1733  out_iter->first = node_index;
1734  out_iter->second = *iter;
1735  }
1736 }
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void ConvertToCindexIds ( const std::vector< Cindex > &  cindexes,
std::vector< int32 > *  cindex_ids 
) const
private

Definition at line 1695 of file nnet-computation-graph.cc.

References ComputationGraph::GetCindexId(), ComputationStepsComputer::graph_, and KALDI_ASSERT.

Referenced by ComputationStepsComputer::ProcessComponentStep(), and ComputationStepsComputer::ProcessDimRangeSubPhase().

1697  {
1698  cindex_ids->resize(cindexes.size());
1699  std::vector<Cindex>::const_iterator iter = cindexes.begin(),
1700  end = cindexes.end();
1701  std::vector<int32>::iterator out_iter = cindex_ids->begin();
1702  for (; iter != end; ++iter, ++out_iter) {
1703  int32 cindex_id = graph_->GetCindexId(*iter);
1704  KALDI_ASSERT(cindex_id >= 0);
1705  *out_iter = cindex_id;
1706  }
1707 }
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void ConvertToIndexes ( const std::vector< Cindex > &  cindexes,
std::vector< Index > *  indexes 
)
staticprivate

Definition at line 1711 of file nnet-computation-graph.cc.

Referenced by ComputationStepsComputer::ProcessComponentStep().

1713  {
1714  indexes->resize(cindexes.size());
1715  std::vector<Cindex>::const_iterator iter = cindexes.begin(),
1716  end = cindexes.end();
1717  std::vector<Index>::iterator out_iter = indexes->begin();
1718  for (; iter != end; ++iter, ++out_iter)
1719  *out_iter = iter->second;
1720 }
void ConvertToLocations ( const std::vector< int32 > &  cindex_ids,
std::vector< std::pair< int32, int32 > > *  locations 
) const
private

Definition at line 1830 of file nnet-computation-graph.cc.

References KALDI_ASSERT, and ComputationStepsComputer::locations_.

Referenced by ComputationStepsComputer::ProcessDimRangeSubPhase().

1832  {
1833  locations->resize(cindex_ids.size());
1834  std::vector<int32>::const_iterator iter = cindex_ids.begin(),
1835  end = cindex_ids.end();
1836  std::vector<std::pair<int32, int32> >::iterator out_iter =
1837  locations->begin();
1838  // note, locations_ and locations are different variables.
1839  std::pair<int32, int32> *locations_ptr = &((*locations_)[0]);
1840  size_t num_cindexes = locations_->size();
1841  for (; iter != end; ++iter, ++out_iter) {
1842  int32 cindex_id = *iter;
1843  KALDI_ASSERT(static_cast<size_t>(cindex_id) < num_cindexes);
1844  int32 step = locations_ptr[cindex_id].first,
1845  row = locations_ptr[cindex_id].second;
1846  KALDI_ASSERT(step >= 0);
1847  out_iter->first = step;
1848  out_iter->second = row;
1849  }
1850 }
std::vector< std::pair< int32, int32 > > * locations_
locations_ is a map from cindex_id to the pair of indexes into steps_ where that cindex_id resides...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void ProcessComponentStep ( const std::vector< Cindex > &  step)
private

Definition at line 1741 of file nnet-computation-graph.cc.

References ComputationStepsComputer::AddStep(), ComputationGraph::cindexes, NetworkNode::component_index, ComputationStepsComputer::ConvertToCindexes(), ComputationStepsComputer::ConvertToCindexIds(), ComputationStepsComputer::ConvertToIndexes(), rnnlm::d, ComputationGraph::dependencies, Nnet::GetComponent(), Nnet::GetNode(), ComputationStepsComputer::graph_, Nnet::IsComponentNode(), KALDI_ASSERT, kaldi::nnet3::kReordersIndexes, kaldi::nnet3::kSimpleComponent, ComputationStepsComputer::nnet_, Component::Properties(), Component::ReorderIndexes(), and NetworkNode::u.

Referenced by ComputationStepsComputer::ProcessSubPhase().

1742  {
1743  KALDI_ASSERT(!step.empty());
1744  int32 component_node_index = step.front().first;
1745  int32 component_input_index = component_node_index - 1;
1746  KALDI_ASSERT(nnet_.IsComponentNode(component_node_index));
1747  const NetworkNode &node = nnet_.GetNode(component_node_index);
1748  int32 c = node.u.component_index;
1749  const Component *component = nnet_.GetComponent(c);
1750  if (component->Properties() & kSimpleComponent) {
1751  // for simple components, the input cindexes will be the same as the
1752  // output ones except for the node index, so we do a shortcut that's
1753  // faster (no following dependencies).
1754  std::vector<Cindex> input_step(step.size());
1755  input_step.resize(step.size());
1756  std::vector<Cindex>::iterator iter = input_step.begin(),
1757  end = input_step.end();
1758  std::vector<Cindex>::const_iterator src = step.begin();
1759  for (; iter != end; ++iter,++src) {
1760  iter->first = component_input_index;
1761  iter->second = src->second;
1762  }
1763  AddStep(input_step);
1764  AddStep(step);
1765  } else {
1766  std::vector<int32> step_cindex_ids;
1767  ConvertToCindexIds(step, &step_cindex_ids);
1768  // to get the input cindexes we need to follow dependencies back.
1769  unordered_set<int32> input_cindex_ids;
1770  std::vector<int32>::iterator iter = step_cindex_ids.begin(),
1771  end = step_cindex_ids.end();
1772  for (; iter != end; ++iter) {
1773  int32 c = *iter;
1774  const std::vector<int32> &dependencies = graph_->dependencies[c];
1775  std::vector<int32>::const_iterator dep_iter = dependencies.begin(),
1776  dep_end = dependencies.end();
1777  for (; dep_iter != dep_end; ++dep_iter) {
1778  int32 d = *dep_iter;
1779  input_cindex_ids.insert(d);
1780  }
1781  }
1782  // Convert to Cindexes so we can sort them as Cindexes.
1783  std::vector<Cindex> input_step;
1784  input_step.reserve(input_cindex_ids.size());
1785  unordered_set<int32>::iterator set_iter = input_cindex_ids.begin(),
1786  set_end = input_cindex_ids.end();
1787  for (; set_iter != set_end; ++set_iter) {
1788  int32 c = *set_iter;
1789  input_step.push_back(graph_->cindexes[c]);
1790  }
1791 
1792  // sort the input cindexes.
1793  std::sort(input_step.begin(), input_step.end());
1794 
1795  if (component->Properties() & kReordersIndexes) {
1796  std::vector<Index> indexes, input_indexes;
1797  ConvertToIndexes(input_step, &input_indexes);
1798  ConvertToIndexes(step, &indexes);
1799 
1800 
1801  size_t orig_size = indexes.size() + input_indexes.size();
1802 
1803  // the component wants to have the opportunity to change the
1804  // order of these indexes from their default.
1805  component->ReorderIndexes(&input_indexes, &indexes);
1806 
1807  bool added_padding = (orig_size != indexes.size() + input_indexes.size());
1808 
1809  // Now convert back from indexes to cindexes (we know the
1810  // node-index in each case)
1811  std::vector<Cindex> reordered_step;
1812  ConvertToCindexes(indexes, component_node_index, &reordered_step);
1813  ConvertToCindexes(input_indexes, component_input_index, &input_step);
1814  // the 'added_padding' argument becomes the 'add_if_absent' arg of
1815  // AddStep, so it knows to expect that it might have to add new CindexIds.
1816  AddStep(input_step, added_padding);
1817  AddStep(reordered_step, added_padding);
1818  } else {
1819  AddStep(input_step);
1820  // it's more efficient to add the step with cindex_ids; and we have these
1821  // available, so we do it that way. (in the other branch where
1822  // the flag kReordersIndexes was present, we couldn't do this because
1823  // of the reordering).
1824  AddStep(&step_cindex_ids);
1825  }
1826  }
1827 }
void ConvertToCindexIds(const std::vector< Cindex > &cindexes, std::vector< int32 > *cindex_ids) const
static void ConvertToIndexes(const std::vector< Cindex > &cindexes, std::vector< Index > *indexes)
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
bool IsComponentNode(int32 node) const
Returns true if this is a component node, meaning that it is of type kComponent.
Definition: nnet-nnet.cc:132
std::vector< std::vector< int32 > > dependencies
dependencies[cindex_id] gives you the list of other cindex_ids that this particular cindex_id directl...
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
void ConvertToCindexes(const std::vector< int32 > &cindex_ids, std::vector< Cindex > *cindexes) const
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
int32 AddStep(const std::vector< Cindex > &cindexes, bool add_if_absent=false)
union kaldi::nnet3::NetworkNode::@14 u
void ProcessDimRangeSubPhase ( const std::vector< Cindex > &  sub_phase)
private

Definition at line 1852 of file nnet-computation-graph.cc.

References ComputationStepsComputer::AddStep(), ComputationStepsComputer::ConvertToCindexes(), ComputationStepsComputer::ConvertToCindexIds(), ComputationStepsComputer::ConvertToLocations(), Nnet::GetNode(), rnnlm::i, Nnet::IsDimRangeNode(), KALDI_ASSERT, ComputationStepsComputer::nnet_, NetworkNode::node_index, ComputationStepsComputer::steps_, and NetworkNode::u.

Referenced by ComputationStepsComputer::ProcessSubPhase().

1853  {
1854  int32 dim_range_node = sub_phase[0].first;
1855  KALDI_ASSERT(nnet_.IsDimRangeNode(dim_range_node));
1856  const NetworkNode &node = nnet_.GetNode(dim_range_node);
1857  // 'input_node_index' is the node index of the component or input node
1858  // that this dim-range node gets its input from.
1859  int32 input_node_index = node.u.node_index;
1860  // input_cindexes will give us the cindexes of the component or input node
1861  // that is the input to this dim-range node
1862  std::vector<Cindex> input_cindexes(sub_phase);
1863  for (std::vector<Cindex>::iterator iter = input_cindexes.begin(),
1864  end = input_cindexes.end(); iter != end; ++iter)
1865  iter->first = input_node_index;
1866  std::vector<int32> input_cindex_ids;
1867  ConvertToCindexIds(input_cindexes, &input_cindex_ids);
1868  std::vector<std::pair<int32, int32> > locations;
1869  ConvertToLocations(input_cindex_ids, &locations);
1870  std::sort(locations.begin(), locations.end());
1871  KALDI_ASSERT(!locations.empty());
1872  std::vector<std::pair<int32, int32> >::const_iterator
1873  locations_iter = locations.begin(),
1874  locations_end = locations.end();
1875  // Each unique .first number in locations (i.e. each source step, and they
1876  // will all correspond to component-output or input steps) will generate one
1877  // 'step' of type kDimRange. Because dim-range nodes must be contiguous
1878  // ranges of a source step (since they are represented as sub-matrices), for
1879  // each source step we work out the first and last row-index (i.e. first and
1880  // last .second member of locations) and use that to reconstruct the range.
1881 
1882  // each element of 'steps' will be (source_step, (begin_row, end_row)) so that
1883  // the source of the dim-range node is indexes begin_row ... end_row-1 in that
1884  // source step.
1885  std::vector<std::pair<int32, std::pair<int32, int32> > > steps;
1886 
1887  int32 cur_source_step = locations_iter->first,
1888  cur_row_begin = locations_iter->second,
1889  cur_row_end = cur_row_begin + 1;
1890  while (1) {
1891  ++locations_iter;
1892  if (locations_iter == locations_end ||
1893  locations_iter->first != cur_source_step) {
1894  // we reached the end of a run of the same step.
1895  std::pair<int32, std::pair<int32, int32> > this_step;
1896  this_step.first = cur_source_step;
1897  this_step.second.first = cur_row_begin;
1898  this_step.second.second = cur_row_end;
1899  steps.push_back(this_step);
1900  if (locations_iter != locations_end) {
1901  cur_source_step = locations_iter->first;
1902  cur_row_begin = locations_iter->second;
1903  cur_row_end = cur_row_begin + 1;
1904  } else {
1905  break;
1906  }
1907  } else {
1908  cur_row_end = locations_iter->second + 1;
1909  }
1910  }
1911 
1912  for (size_t i = 0; i < steps.size(); i++) {
1913  // iterating over different source steps, although normally
1914  // there will be just one.
1915  int32 source_step = steps[i].first,
1916  row_begin = steps[i].second.first,
1917  row_end = steps[i].second.second;
1918  // 'source' is just the elements of the source step that we're consuming.
1919  std::vector<int32> source((*steps_)[source_step].begin() + row_begin,
1920  (*steps_)[source_step].begin() + row_end);
1921  std::vector<Cindex> cindexes;
1922  ConvertToCindexes(source, &cindexes);
1923  std::vector<Cindex>::iterator iter = cindexes.begin(),
1924  end = cindexes.end();
1925  for (; iter != end; ++iter)
1926  iter->first = dim_range_node;
1927  bool add_if_absent = true;
1928  // this add_if_absent says, even if cindexes were not in the graph,
1929  // add them. This is possible in principle; it's to satisfy the
1930  // requirement that DimRangeNodes be implemented as contiguous ranges
1931  // of rows of component nodes or input nodes.
1932  AddStep(cindexes, add_if_absent);
1933  }
1934 }
void ConvertToCindexIds(const std::vector< Cindex > &cindexes, std::vector< int32 > *cindex_ids) const
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
bool IsDimRangeNode(int32 node) const
Returns true if this is a dim-range node, meaning that it is of type kDimRange.
Definition: nnet-nnet.cc:138
std::vector< std::vector< int32 > > * steps_
steps_ is a pointer to an output that's passed in in the constructor.
void ConvertToCindexes(const std::vector< int32 > &cindex_ids, std::vector< Cindex > *cindexes) const
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
int32 AddStep(const std::vector< Cindex > &cindexes, bool add_if_absent=false)
void ConvertToLocations(const std::vector< int32 > &cindex_ids, std::vector< std::pair< int32, int32 > > *locations) const
union kaldi::nnet3::NetworkNode::@14 u
void ProcessInputOrOutputStep ( const ComputationRequest request,
bool  is_output,
const std::vector< Cindex > &  sub_phase 
)
private

Definition at line 1567 of file nnet-computation-graph.cc.

References ComputationStepsComputer::AddStep(), ComputationGraph::GetCindexId(), Nnet::GetNodeName(), ComputationStepsComputer::graph_, rnnlm::i, ComputationRequest::inputs, Nnet::IsInputNode(), Nnet::IsOutputNode(), KALDI_ASSERT, ComputationStepsComputer::locations_, ComputationStepsComputer::nnet_, and ComputationRequest::outputs.

Referenced by ComputationStepsComputer::ProcessSubPhase().

1570  {
1571  int32 io_node = sub_phase[0].first;
1572  if (is_output){
1573  KALDI_ASSERT(nnet_.IsOutputNode(io_node));
1574  } else {
1575  KALDI_ASSERT(nnet_.IsInputNode(io_node));
1576  }
1577  std::string node_name = nnet_.GetNodeName(io_node);
1578  const std::vector<IoSpecification> &inputs_or_outputs =
1579  (is_output ? request.outputs : request.inputs);
1580  int32 io_index = -1;
1581  for (size_t i = 0; i < inputs_or_outputs.size(); i++)
1582  if (inputs_or_outputs[i].name == node_name)
1583  io_index = i;
1584  KALDI_ASSERT(io_index >= 0);
1585  const std::vector<Index> &io_indexes = inputs_or_outputs[io_index].indexes;
1586  std::vector<Cindex> io_cindexes(io_indexes.size());
1587  for (size_t i = 0, size = io_cindexes.size(); i < size; i++) {
1588  io_cindexes[i].first = io_node;
1589  io_cindexes[i].second = io_indexes[i];
1590  }
1591  KALDI_ASSERT(io_cindexes.size() == sub_phase.size());
1592  // we expect the list of cindexes in 'io_cindexes' to be identical to
1593  // that in 'sub_phase' (but they don't have to be in the same order)... for now we check the size, we'll spot-check
1594  // that they are the same later.
1595  // The actual output in 'steps' must be in the same order as
1596  int32 step_index = AddStep(io_cindexes);
1597  // Now spot-check that the cindexes in 'sub_phase' are the same as those
1598  // we just added. [note: they don't have to be in the same order, but
1599  // they should be the same set.]
1600  for (size_t i = 0; i < sub_phase.size(); i += 10) {
1601  const Cindex &cindex = sub_phase[i];
1602  int32 cindex_id = graph_->GetCindexId(cindex);
1603  KALDI_ASSERT(cindex_id >= 0 && (*locations_)[cindex_id].first == step_index);
1604  }
1605 }
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112
bool IsInputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kInput.
Definition: nnet-nnet.cc:120
std::vector< std::pair< int32, int32 > > * locations_
locations_ is a map from cindex_id to the pair of indexes into steps_ where that cindex_id resides...
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
const std::string & GetNodeName(int32 node_index) const
returns individual node name.
Definition: nnet-nnet.cc:684
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
int32 AddStep(const std::vector< Cindex > &cindexes, bool add_if_absent=false)
void ProcessSubPhase ( const ComputationRequest request,
const std::vector< Cindex > &  sub_phase 
)
private

Definition at line 1936 of file nnet-computation-graph.cc.

References Nnet::IsComponentInputNode(), Nnet::IsComponentNode(), Nnet::IsDimRangeNode(), Nnet::IsInputNode(), Nnet::IsOutputNode(), KALDI_ASSERT, KALDI_ERR, ComputationStepsComputer::nnet_, ComputationStepsComputer::ProcessComponentStep(), ComputationStepsComputer::ProcessDimRangeSubPhase(), and ComputationStepsComputer::ProcessInputOrOutputStep().

Referenced by ComputationStepsComputer::ComputeForSegment().

1938  {
1939  KALDI_ASSERT(!sub_phase.empty());
1940  int32 node_index = sub_phase[0].first;
1941  KALDI_ASSERT(sub_phase.back().first == node_index);
1942  if (nnet_.IsComponentNode(node_index)) {
1943  ProcessComponentStep(sub_phase);
1944  } else if (nnet_.IsInputNode(node_index)) {
1945  ProcessInputOrOutputStep(request, false, sub_phase);
1946  } else if (nnet_.IsOutputNode(node_index)) {
1947  ProcessInputOrOutputStep(request, true, sub_phase);
1948  } else if (nnet_.IsDimRangeNode(node_index)) {
1949  // this might turn out to be multiple steps, see the code.
1950  ProcessDimRangeSubPhase(sub_phase);
1951  } else if (nnet_.IsComponentInputNode(node_index)) {
1952  // We actually do nothing with these sub-phases, because they are processed
1953  // when we process the associated component's sub-phase/step. Doing it this
1954  // way resolves certain problems.
1955  return;
1956  } else {
1957  KALDI_ERR << "Unknown node type.";
1958  }
1959 }
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112
bool IsInputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kInput.
Definition: nnet-nnet.cc:120
void ProcessDimRangeSubPhase(const std::vector< Cindex > &sub_phase)
bool IsComponentNode(int32 node) const
Returns true if this is a component node, meaning that it is of type kComponent.
Definition: nnet-nnet.cc:132
bool IsDimRangeNode(int32 node) const
Returns true if this is a dim-range node, meaning that it is of type kDimRange.
Definition: nnet-nnet.cc:138
#define KALDI_ERR
Definition: kaldi-error.h:127
void ProcessComponentStep(const std::vector< Cindex > &step)
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void ProcessInputOrOutputStep(const ComputationRequest &request, bool is_output, const std::vector< Cindex > &sub_phase)
bool IsComponentInputNode(int32 node) const
Returns true if this is component-input node, i.e.
Definition: nnet-nnet.cc:172
void SplitIntoSubPhases ( const std::vector< int32 > &  phase,
std::vector< std::vector< Cindex > > *  sub_phase 
) const
private

Definition at line 1983 of file nnet-computation-graph.cc.

References ComputationStepsComputer::ConvertToCindexes(), rnnlm::i, and KALDI_ASSERT.

Referenced by ComputationStepsComputer::ComputeForSegment().

1985  {
1986  std::vector<Cindex> phase_cindexes;
1987  ConvertToCindexes(phase, &phase_cindexes);
1988  KALDI_ASSERT(!phase_cindexes.empty());
1989  std::sort(phase_cindexes.begin(), phase_cindexes.end());
1990  // 'sub_phase_begins' is the indexes onto 'phase_cindees' that
1991  // start a run of the same node-index
1992  std::vector<size_t> segment_begins;
1993  int32 cur_node_index = -1;
1994  size_t size = phase_cindexes.size();
1995  for (size_t i = 0; i < size; i++) {
1996  if (phase_cindexes[i].first != cur_node_index) {
1997  cur_node_index = phase_cindexes[i].first;
1998  segment_begins.push_back(i);
1999  }
2000  }
2001  size_t num_sub_phases = segment_begins.size();
2002  segment_begins.push_back(size);
2003  sub_phases->clear();
2004  sub_phases->resize(num_sub_phases);
2005  for (size_t i = 0; i < num_sub_phases; i++) {
2006  size_t this_begin = segment_begins[i],
2007  this_end = segment_begins[i+1];
2008  (*sub_phases)[i].insert((*sub_phases)[i].end(),
2009  phase_cindexes.begin() + this_begin,
2010  phase_cindexes.begin() + this_end);
2011  }
2012 }
void ConvertToCindexes(const std::vector< int32 > &cindex_ids, std::vector< Cindex > *cindexes) const
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169

Member Data Documentation

std::vector<std::pair<int32, int32> >* locations_
private

locations_ is a map from cindex_id to the pair of indexes into steps_ where that cindex_id resides, so if (*locations_)[c] = (i,j), then (*steps_)[i][j] == c.

This is also an output (we get the pointer in the constructor).

Definition at line 549 of file nnet-computation-graph.h.

Referenced by ComputationStepsComputer::AddStep(), ComputationStepsComputer::Check(), ComputationStepsComputer::ComputationStepsComputer(), ComputationStepsComputer::ConvertToLocations(), and ComputationStepsComputer::ProcessInputOrOutputStep().

std::vector<std::vector<int32> >* steps_
private

The documentation for this class was generated from the following files: