cinn_cache_key.cc 4.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/fluid/framework/paddle2cinn/cinn_cache_key.h"

17 18
#include <algorithm>
#include <functional>
19
#include <map>
20
#include <set>
21 22 23 24 25
#include <string>

#include "paddle/fluid/framework/ddim.h"
#include "paddle/fluid/framework/ir/graph.h"
#include "paddle/fluid/framework/lod_tensor.h"
26
#include "paddle/fluid/inference/analysis/dot.h"
27 28 29 30 31 32 33

namespace paddle {
namespace framework {
namespace paddle2cinn {

CinnCacheKey::CinnCacheKey(
    const ir::Graph& graph,
34 35 36
    const std::map<std::string, const LoDTensor*>& input_tensors,
    const std::string& arch_str) {
  this->SetKey(graph, input_tensors, arch_str);
37 38 39
}

CinnCacheKey::CinnCacheKey(const ir::Graph& graph,
40 41 42
                           const std::map<std::string, DDim>& input_shapes,
                           const std::string& arch_str) {
  this->SetKey(graph, input_shapes, arch_str);
43 44
}

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
size_t CinnCacheKey::HashGraph(const ir::Graph& graph) {
  // using Dot to unqiue graph
  inference::analysis::Dot dot;
  std::unordered_map<const ir::Node*, std::string> node2dot;
  int id = 0;
  // Create nodes
  // graph.Nodes() return unordered_set, the same graph may
  // return different result?
  for (const ir::Node* n : graph.Nodes()) {
    std::string node_id = std::to_string(id++);
    dot.AddNode(node_id, {}, n->Name(), true);
    node2dot[n] = node_id;
  }

  // Create edges
  for (const ir::Node* n : graph.Nodes()) {
    const auto& src_id = node2dot.at(n);
    for (auto* out : n->outputs) {
      const auto& dest_id = node2dot.at(out);
      dot.AddEdge(src_id, dest_id, {});
    }
  }

  const std::string& viz_graph = dot.Build();
  VLOG(1) << "The hash graph:\n" << viz_graph;

  size_t hash_val = std::hash<std::string>()(viz_graph);
  VLOG(4) << "The graph's hash value is: " << hash_val;
  return hash_val;
}

76 77
void CinnCacheKey::SetKey(
    const ir::Graph& graph,
78 79
    const std::map<std::string, const LoDTensor*>& input_tensors,
    const std::string& arch_str) {
80
  graph_serialize_str_ = std::to_string(HashGraph(graph));
81 82
  for (const auto& name_tensor : input_tensors) {
    input_shapes_[name_tensor.first] = name_tensor.second->dims();
83
  }
84
  arch_str_ = arch_str;
85 86 87
}

void CinnCacheKey::SetKey(const ir::Graph& graph,
88 89
                          const std::map<std::string, DDim>& input_shapes,
                          const std::string& arch_str) {
90
  graph_serialize_str_ = std::to_string(HashGraph(graph));
91 92
  input_shapes_ = input_shapes;
  arch_str_ = arch_str;
93 94 95 96 97 98 99 100
}

bool CinnCacheKey::operator!=(const CinnCacheKey& other) const {
  return !this->operator==(other);
}

bool CinnCacheKey::operator==(const CinnCacheKey& other) const {
  return graph_serialize_str_ == other.graph_serialize_str_ &&
101
         input_shapes_ == other.input_shapes_ && arch_str_ == other.arch_str_;
102 103 104 105 106 107 108 109 110 111
}

size_t CinnCacheKey::Hash::hash_combine(size_t seed, size_t value) {
  return seed ^ (value + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}

size_t CinnCacheKey::Hash::operator()(const CinnCacheKey& key) const {
  std::size_t ret = 0;

  std::hash<std::string> string_hasher;
112
  for (const auto& name_shape : key.input_shapes_) {
113 114 115 116 117
    ret = hash_combine(ret, string_hasher(name_shape.first));
    ret = hash_combine(ret, string_hasher(name_shape.second.to_str()));
  }

  ret = hash_combine(ret, string_hasher(key.graph_serialize_str_));
118
  ret = hash_combine(ret, string_hasher(key.arch_str_));
119 120 121 122 123 124
  return ret;
}

}  // namespace paddle2cinn
}  // namespace framework
}  // namespace paddle