message: Make segmenter deterministic
diff: @@ -225,6 +225,24 @@ SimpleGraph::~SimpleGraph() {
  for (auto x : edges_) delete x;
  }
  +// Define comparison functions for std::set with pointer keys so that behavior
  +// is deterministic. When using std::set with pointer key types, the items are
  +// sorted by pointer address which is non-deterministic. This can cause issues
  +// for INT8 mode because the graph is converted twice and non-determinism may
  +// cause a mismatch between the calibration tables of the conversions.
  +struct SimpleEdgePtrCompare {
  + bool operator()(const SimpleEdge* lhs, const SimpleEdge* rhs) const {
  + return (lhs->id() < rhs->id());
  + }
  +};
  +
  +struct NodePtrCompare {
  + bool operator()(const tensorflow::Node* lhs,
  + const tensorflow::Node* rhs) const {
  + return (lhs->name() < rhs->name());
  + }
  +};
  +
  namespace {
  // Copied from TF ReverseDFS, which only works for tensorflow::Graph.
  @@ -476,7 +494,7 @@ tensorflow::Status SegmentGraph(
  // nodes. Iterate since combining two nodes may unblock other
  // combining.
  while (true) {
  - std::set<const SimpleEdge*> contract_edges;
  + std::set<const SimpleEdge*, SimpleEdgePtrCompare> contract_edges;
  for (const SimpleEdge* out_edge : node->out_edges()) {
  VLOG(3) << "... out node " << out_edge->dst()->name() << " ( "
  << out_edge->dst()->id() << " <- " << node->id() << " )";
  @@ -530,7 +548,7 @@ tensorflow::Status SegmentGraph(
  // A map from the segment identifier (currently the name of the root node of
  // the segment tree) to the segment nodes set.
  - std::map<string, std::set<const tensorflow::Node*>> sg_map;
  + std::map<string, std::set<const tensorflow::Node*, NodePtrCompare>> sg_map;
  // A map from the segment identifier (currently the name of the root node of
  // the segment tree) to the device names that the nodes in the segment are
  @@ -566,7 +584,8 @@ tensorflow::Status SegmentGraph(
  // --------------------------------- Step 2 ---------------------------------
  // Remove ineligible input/output nodes.
  for (auto& itr : sg_map) {
  - std::set<const tensorflow::Node*>& segment_nodes = itr.second;
  + std::set<const tensorflow::Node*, NodePtrCompare>& segment_nodes =
  + itr.second;
  VLOG(1) << "Segment original size: " << segment_nodes.size();
  while (true) {
  std::deque<const tensorflow::Node*> in_nodes_que, out_nodes_que;
  @@ -618,8 +637,9 @@ tensorflow::Status SegmentGraph(
  bool is_input_nodes,
  std::deque<const tensorflow::Node*>* que) {
  // Run a BFS on the queue to find all the input/output nodes.
  - std::set<const tensorflow::Node*> visited;
  - std::set<const tensorflow::Node*> logged(que->begin(), que->end());
  + std::set<const tensorflow::Node*, NodePtrCompare> visited;
  + std::set<const tensorflow::Node*, NodePtrCompare> logged(que->begin(),
  + que->end());
  while (!que->empty()) {
  auto node = que->front();
  que->pop_front();
  @@ -653,7 +673,8 @@ tensorflow::Status SegmentGraph(
  // --------------------------------- Step 3 ---------------------------------
  // Convert the segments into the expected return format
  for (const auto& itr : sg_map) {
  - const std::set<const tensorflow::Node*>& segment_nodes = itr.second;
  + const std::set<const tensorflow::Node*, NodePtrCompare>& segment_nodes =
  + itr.second;
  if (VLOG_IS_ON(1)) {
  string s = "parent=" + itr.first + ":";
  for (auto node : segment_nodes) s += " " + node->name();
  