SlideShare a Scribd company logo
1 of 93
Download to read offline
Bridge TensorFlow* to run on Intel®
nGraph™ backends
v0.4 : ソースコード解析
作成:2018/07/16, 21, 08/11
Slideshareにて公開
  :2018/09/04
@Vengineer
ブログ (2007年~) : Vengineerの戯言
 http://blogs.yahoo.co.jp/verification_engineer
SlideShare :
 https://www.slideshare.net/ssuser479fa3
Twitter (2009年~) :
@Vengineer
最近は、ソースコード解析職人
https://github.com/NervanaSystems/ngraph
Intel nGraph library
ONNX
neon
TensorFlow
MXNet
NNP = ARGON ?
TensorFlow r1.3
XLA + Intel nGraph
@Vengineer
2018/03/21, 03/25
03/29に新しいコードが公開され、
このコードはgithubから削除されたのでお蔵入り。
TensorFlow
dynamically loadable XLA plugin
proposal
https://blogs.yahoo.co.jp/verification_engineer/71526428.html
2018/04/09
TensorFlow
dynamically loadable XLA plugin の内容
https://blogs.yahoo.co.jp/verification_engineer/71526444.html
2018/04/10
TensorFlow Dynamically loadable XLA
Pluginソースコード解析
https://leapmind.connpass.com/event/87729/
2018/05/25(水)@LeapMind
TensorFlow
dynamically loadable XLA plugin
https://github.com/NervanaSystems/ngraph-tensorflow
tensorflow/compiler/plugin/dynamic
TensorFlowのXLA側のコードの修正必要が無くなる
ええええ、XLA無しのブリッジだって?
/XLAが無くなっているよ。。。。
https://github.com/NervanaSystems/ngraph-tf
Bridge TensorFlow* to run on Intel®
nGraph™ backends
https://github.com/NervanaSystems/ngraph-tf
https://github.com/NervanaSystems/ngraph-tf/tree/r0.4/
復習
TensorFlowでのグラフ表現
まずは、cpu で確認してみると
def test_cpu(self):
with tf.Session() as sess:
x = tf.placeholder(tf.float32, [2], name="x")
with tf.device("cpu"):
y = x * 2
result = sess.run(y, {x: [1.5, 0.5]})
0)、最初
Mul
Const
Feed(x)
Fetch(y)
1)、Feed/Fetchノードの追加
Mul
_Recv
Const
_Send
Feed(x)
Fetch(y)
2)、Placement
Mul
_Recv
Const
_Send
cpu : Feed(x)
cpu : Fetch(y)
cpu
cpu
3)、グラフの分割
Mul
_Recv
Const
_Send
cpu : Feed(x)
cpu : Fetch(y)
cpu
cpu
次に、gpu に変更してみると
def test_gpu(self):
with tf.Session() as sess:
x = tf.placeholder(tf.float32, [2], name="x")
with tf.device("gpu"):
y = x * 2
result = sess.run(y, {x: [1.5, 0.5]})
0)、最初
Mul
Const
Feed(x)
Fetch(y)
1)、Feed/Fetchノードの追加
Mul
_Recv
Const
_Send
Feed(x)
Fetch(y)
2)、Placement
Mul
_Recv
Const
_Send
cpu : Feed(x)
cpu : Fetch(y)
gpu
gpu
3)、グラフの分割
_Recv
_Recv
_Send
_Send _Recv _Send
gpu
Feed(x) Fetch(y)cpu
Mul
Const
NGRAPH
デバイスの登録
デバイスの登録
core/common_runtime/device_factory.{h,c}
// The default priority values for built-in devices is:
// GPU: 210
// SYCL: 200
// GPUCompatibleCPU: 70
// ThreadPoolDevice: 60
// Default: 50
REGISTER_LOCAL_DEVICE_FACTORY マクロで設定する
src/ngraph_device.cc
class NGraphDevice : public Device {
public:
explicit NGraphDevice(const DeviceAttributes& attr) : Device(nullptr, attr) {
m_allocator = cpu_allocator();
m_device_context = new NGraphDeviceContext();
m_device_context->Ref();
}
~NGraphDevice() { m_device_context->Unref(); }
Status Sync() override { return Status::OK(); }
…..
private:
tf::Allocator* m_allocator;
NGraphDeviceContext* m_device_context; // not owned
};
NGraphDevice
src/ngraph_device.cc
namespace ngraph_bridge {
extern const char* const DEVICE_NGRAPH = "NGRAPH";
}
class NGraphDeviceFactory : public DeviceFactory {
public:
Status CreateDevices(const SessionOptions& options, const string& name_prefix,
std::vector<Device*>* devices) override {
DeviceAttributes attr;
attr.set_name(strings::StrCat(name_prefix, "/device:NGRAPH:0"));
attr.set_device_type(ngraph_bridge::DEVICE_NGRAPH);
devices->push_back(new NGraphDevice(attr));4
return Status::OK();
}
};
REGISTER_LOCAL_DEVICE_FACTORY( ngraph_bridge::DEVICE_NGRAPH,
NGraphDeviceFactory, 50 );
NGraphDeviceFactory
グラフの変形
Passを使ってグラフの変形を行っている
 1)、Feed/Fetchノードの追加
subgraph::RewriteGraphForExecution
ここで、PRE_PLACEMENTパス を実行
 2)、Placement
ここで、POST_PLACEMENTパス を実行
  SimpleGraphExecutionState::BuildGraph関数で
   POST_REWRITE_FOR_EXECパス を実行
 3)、グラフの分割
Partition
ここで、POST_PARTITIONINGパス を実行
OptimizationPass
tensorflow/core/common_runtime/optimization_registry.h
class OptimizationPassRegistry {
public:
// Groups of passes are run at different points in initialization.
enum Grouping {
PRE_PLACEMENT, // after cost model assignment, before placement.
POST_PLACEMENT, // after placement.
POST_REWRITE_FOR_EXEC, // after re-write using feed/fetch endpoints.
POST_PARTITIONING, // after partitioning
};
PRE_PLACEMENT, 80, NGraphLiberatePass
PRE_PLACEMENT, 90, NGraphConfirmPass
PRE_PLACEMENT, 100, NGraphDumpPrePlacement
POST_PLACEMENT, 100, NGraphDumpPostPlacement
POST_REWRITE_FOR_EXEC, 100, NGraphDumpPostReWrite
POST_REWRITE_FOR_EXEC, 105, NGraphClusterPass    // クラスタ化
POST_REWRITE_FOR_EXEC, 105, NGraphDumpPostClustering
POST_REWRITE_FOR_EXEC, 110, NGraphEncapsulatePass // Op化
POST_REWRITE_FOR_EXEC, 115, NGraphDumpPostEncapsulation
POST_PARTITIONING, 100, NGraphDumpPostPartitioning
最適化パス
次に、NGRAPH に変更してみると
def test_ngraph(self):
with tf.Session() as sess:
x = tf.placeholder(tf.float32, [2], name="x")
with tf.device("NGRAPH"):
y = x * 2
result = sess.run(y, {x: [1.5, 0.5]})
0)、最初
Mul
Const
Feed(x)
Fetch(y)
1)、Feed/Fetchノードの追加
Mul
_Recv
Const
_Send
Feed(x)
Fetch(y)
2)、Placement
Mul
_Recv
Const
_Send
cpu : Feed(x)
cpu : Fetch(y)
NGRAPH
NGRAPH
3)、グラフの分割
_Recv
_Recv
_Send
_Send _Recv _Send
NGRAPH
Feed(x) Fetch(y)cpu
Mul
Const
PRE_PLACEMENT
1)、NGraphLiberatePass
2)、NGraphConfirmPass
最適化パス
src/ngraph_liberate_pass.cc
REGISTER_OPTIMIZATION(
OptimizationPassRegistry::PRE_PLACEMENT,
80,
ngraph_bridge::NGraphLiberatePass);
NGraphLiberatePass
src/ngraph_liberate_pass.cc
class NGraphLiberatePass : public tensorflow::GraphOptimizationPass {
public:
tf::Status Run(const tf::GraphOptimizationPassOptions& options) {
return LiberateNGraphPlacement(options.graph->get());
}
private:
static bool IsNGraphNode(const tf::Node* node);
tf::Status LiberateNGraphPlacement(tf::Graph* graph);
};
NGraphLiberatePass
src/ngraph_liberate_pass.cc
tf::Status LiberateNGraphPlacement(tf::Graph* graph) {
int i = 0;
for (auto node : graph->op_nodes()) {
if (node->IsOp() && IsNGraphNode(node)) {
std::vector<std::string> colo;
if (tf::GetNodeAttr(node->attrs(), tf::kColocationAttrName, &colo) == tf::Status::OK()) {
for (auto& s : colo) {
std::stringstream ss; ss << s << "/LIBERATED_" << (i++); s = ss.str();
}
node->ClearAttr(tf::kColocationAttrName);
node->AddAttr(tf::kColocationAttrName, colo);
}
}
}
return tf::Status::OK();
}
NGraphLiberatePass
src/ngraph_liberate_pass.cc
// At graph construction time, TensorFlow likes to place colocation constraints
// that force variables onto the same device as their initializers. For nGraph
// this doesn't work very well, because we don't yet support RNG ops, and this
// results in randomly-initialized variables being forced onto the host.
//
// The workaround implemented here is to "liberate" nGraph-placed ops from
// colocation constraints. This pass only applies to nodes with a requested
// placement on NGRAPH, meaning that the graph will be unchanged except
// where the user has explicitly requested nGraph.
NGraphLiberatePass
src/ngraph_liberate_pass.cc
// General algorithm:
//
// i := 0
// For each node n in the graph:
// If n has been placed on device NGRAPH:
// For each colocation constraint s on n:
// Append the string ("/LIBERATED_" + i) to s
// i++
//
// (Note that simply blanking out the colocation constraints does not work,
// because this causes the placer to act as if the node is subject to an
// eponymous colocation constraint, which happens to be exactly the name that
// the variable construction stuff will assign to it anyway.)
NGraphLiberatePass
src/ngraph_confirm_pass.cc
REGISTER_OPTIMIZATION(
OptimizationPassRegistry::PRE_PLACEMENT,
90,
ngraph_bridge::NGraphConfirmPass);
NGraphConfirmPass
src/ngraph_confirm_pass.cc
class NGraphConfirmPass : public tensorflow::GraphOptimizationPass {
public:
tf::Status Run(const tf::GraphOptimizationPassOptions& options) {
return ConfirmPlacement(options.graph->get());
}
private:
using ConfirmationFunction = std::function<tf::Status(tf::Node*, bool*)>;
static bool NGraphPlacementRequested(const tf::Node* node) ;
static tf::Status ExtractConstantData(tf::Node* node, std::vector<tf::int64>* values);
tf::Status ConfirmPlacement(tf::Graph* graph) ;
};
NGraphConfirmPass
src/ngraph_confirm_pass.cc
// In some cases, we require more complex placement constraints than than
// TensorFlow's native "soft-placement" machinery is capable of handling. To
// handle this, we insert a pass called the "confirmation" pass during the
// pre-placement phase.
// For example, we can only handle Reshape if the "shape" input is a constant,
// so this is okay:
//
// ... Const[2,4,2]
//  /
// Reshape (1)
//
// but this is not:
//
// ... Placeholder
//  /
// Reshape (2)
NGraphConfirmPass
src/ngraph_confirm_pass.cc
// We want to reject placement of Reshape on NGRAPH for the second graph, but
// allow it for the first. We also want to attach some more metadata to the
// Reshape node so that we can remember the requested output shape even if the
// Const node winds up being placed in a different subgraph.
//
// This pass exploits a feature of the placement engine that allows a kernel
// builder registration request to restrict use of the kernel to nodes that
// have a particular value set for the "_kernel" attribute. In this case, we
// will check every node that has a requested placement on NGRAPH, and make
// sure that it conforms to certain (op-dependent) constraints. If the
// constraints are satisfied, we will tag the node with a "_kernel" value of
// "ngraph", along with some op-specific metadata (if applicable). The stub
// kernels, in turn, are registered with the constraint that _kernel="ngraph".
// This means that during the placement pass, our kernels will not be allowed
// for nodes we did not mark during this pass, and placement will fall back on
// CPU.
NGraphConfirmPass
src/ngraph_confirm_pass.cc
// Taking Reshape as an example, the pass ensures that the "shape" input is
// constant, and if so, it adds to the Reshape node the "_kernel=ngraph"
// attribute, along with some metadata recording the value of the constant.
// Thus graph (1) is transformed as follows:
//
// ... Const[2,4,2][_kernel="ngraph"]
//  /
// Reshape[_kernel="ngraph",
// _ngraph_reshape_static_shape={2,4,2}]
//
// while graph (2) would be left unchanged, meaning that soft placement will
// fall back on non-nGraph implementations.
NGraphConfirmPass
src/ngraph_confirm_pass.cc
// Internally, there are two pieces. The first is a type constraint checker,
// which supplants the type checking machinery usually used with
// REGISTER_KERNEL_BUILDER. This ensures that any constraints on the data types
// of input tensors are satisfied---for example, we do not support DT_STRING.
// The second part is a set of finer-grained per-op checks called "confirmation
// functions", implementing more specific checks like the one described for
// Reshape above.
//
// The confirmation functions are implemented as callbacks of the type:
//
// std::function<tf::Status(tf::Node*, bool*)>.
NGraphConfirmPass
src/ngraph_confirm_pass.cc
// A confirmation function returns true/false by reference through its second
// parameter: true if placement is "accepted", and false if it is "rejected".
// For example, the confirmation function for "Reshape" will return true
// for (1) above, and false for (2).
//
// A confirmation function can also, as a side effect, add attributes to the
// node being checked, which can be used later in ngraph_builder. (Note that in
// general such attributes will need to start with "_" to mark them as
// "internal" or "system" attributes, as otherwise TensorFlow attempts to
// validate them as against the op schema.)
NGraphConfirmPass
POST_REWRITE_FOR_EXEC
1)、NGraphClusterPass
 ・TensorFlow XLAでの サブグラフ の分割と同じこと
2)、NGraphEncapsulatePass
 ・分割した サブグラフ を NGraphEncapsulateOp に変換
  これも、TensorFlow XLAでの _XlaLaunchOp に変換と同じこと
最適化パス
src/ngraph_cluster.cc
namespace tensorflow {
REGISTER_OPTIMIZATION(
OptimizationPassRegistry::POST_REWRITE_FOR_EXEC,
105,
ngraph_bridge::NGraphClusterPass);
}
NGraphClusterPass
src/ngraph_cluster.cc
tf::Status NGraphClusterPass::Run(
const tf::GraphOptimizationPassOptions& options) {
// TODO(amprocte): Remove this when we have proper support for graphs with
// cycles.
if (std::getenv("NGRAPH_TF_SKIP_CLUSTERING") != nullptr) {
return tf::Status::OK();
}
tf::Graph* graph = options.graph->get();
return IdentifyClusters(graph); // ここで NGRAPH でのグラフ構築
}
NGraphClusterPass::Run
src/ngraph_cluster.cc
tf::Status NGraphClusterPass::IdentifyClusters(tf::Graph* graph) {
NGRAPH_VLOG(2) << "Starting contraction";
NGRAPH_VLOG(2) << "Contraction done";
NGRAPH_VLOG(2) << "Starting tagging";
NGRAPH_VLOG(2) << "Tagging done";
}
// nGraphのClusterに分割しているっぽい。
NGraphClusterPass::IdentifyClusters
src/ngraph_encapsulate_pass.cc
namespace tensorflow {
REGISTER_OPTIMIZATION(
OptimizationPassRegistry::POST_REWRITE_FOR_EXEC,
110,
ngraph_bridge::NGraphEncapsulatePass);
} // namespace tensorflow
NGraphEncapsulatePass
src/ngraph_cluster.h
class NGraphEncapsulatePass : public tensorflow::GraphOptimizationPass {
public:
tf::Status Run(const tf::GraphOptimizationPassOptions& options) {
if (std::getenv("NGRAPH_TF_SKIP_ENCAPSULATION") != nullptr) {
NGRAPH_VLOG(0)
<< "NGRAPH_TF_SKIP_ENCAPSULATION is set. Skipping encapsulation "
"step.";
return tf::Status::OK();
}
return EncapsulateFunctions(options.graph->get());
}
…….
};
NGraphEncapsulatePass
src/ngraph_encapsulate_pass.cc
tf::Status EncapsulateFunctions(tf::Graph* graph) {
// Pass 1: Populate the cluster-index-to-device name map for each existing
// cluster.
// Pass 2: Find all nodes that are feeding into/out of each cluster, and
// add inputs for them to the corresponding FunctionDef(s).
// 各クラスタに入力部分がある場合は、入力ノードを追加?
NGraphEncapsulatePass::EncapsulateFunctions
src/ngraph_encapsulate_pass.cc
// Pass 2: Find all nodes that are feeding into/out of each cluster, and
// add inputs for them to the corresponding FunctionDef(s).
// 各クラスタに入力部分がある場合は、入力ノード /出力ノードの追加?
auto new_input_node_def =
NGraphClusterManager::GetClusterGraph(dst_cluster_idx)->add_node();
new_input_node_def->set_name(new_input_name);
new_input_node_def->set_op("_Arg");
SetAttrValue(dt, &((*(new_input_node_def->mutable_attr()))["T"]));
SetAttrValue(arg_index_count[dst_cluster_idx],
&((*(new_input_node_def->mutable_attr()))["index"]));
NGraphEncapsulatePass::EncapsulateFunctions
src/ngraph_encapsulate_pass.cc
// Pass 3: Create encapsulation nodes for all clusters.
// 1つのクラスタが1つのNGraphEncapsulateノードになる
tf::Node* n;
tf::Status status =
tf::NodeBuilder(ss.str(), "NGraphEncapsulate") // <= NGraphEncapsulateノードを
.Attr("ngraph_cluster", cluster_idx)
.Attr("Targuments", input_types)
.Attr("Tresults", cluster_output_dt_map[cluster_idx])
.Device(device_name_map[cluster_idx])
.Input(inputs)
.Finalize(graph, &n);
TF_RETURN_IF_ERROR(status);
n->set_assigned_device_name(device_name_map[cluster_idx]);
cluster_node_map[cluster_idx] = n;
}
NGraphEncapsulatePass::EncapsulateFunctions
src/ngraph_encapsulate_pass.cc
// Pass 4: Remap all non-clustered inputs that are reading from
// encapsulated edges, and all control edges that cross cluster
// boundaries.
// Pass 5: Make copies of all clustered nodes inside the cluster graphs,
// rewiring the inputs in their NodeDefs as we go.
// Pass 6: Remove clustered nodes from the graph.
NGraphEncapsulatePass::EncapsulateFunctions
src/ngraph_encapsulate_pass.cc
// Pass 7 (optional, only run if environment variable
// NGRAPH_TF_VALIDATE_CLUSTER_GRAPHS is set):
// validate the graph def, and make sure we can construct a graph from it.
NGraphEncapsulatePass::EncapsulateFunctions
src/ngraph_graph_rewrite_passes.cc
REGISTER_OPTIMIZATION(OptimizationPassRegistry::PRE_PLACEMENT, 100,
ngraph_bridge::NGraphDumpPrePlacement);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::POST_PLACEMENT, 100,
ngraph_bridge::NGraphDumpPostPlacement);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::POST_REWRITE_FOR_EXEC, 100,
ngraph_bridge::NGraphDumpPostReWrite);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::POST_REWRITE_FOR_EXEC, 105,
ngraph_bridge::NGraphDumpPostClustering);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::POST_REWRITE_FOR_EXEC, 115,
ngraph_bridge::NGraphDumpPostEncapsulation);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::POST_PARTITIONING, 100,
ngraph_bridge::NGraphDumpPostPartitioning);
Passを使ってグラフをダンプしているよ
/src/ngraph_graph_rewrite_passes.cc
class NGraphDumpPrePlacement : public NGraphDumpPass {
public:
NGraphDumpPrePlacement() : NGraphDumpPass("pre_placement") {}
};
class NGraphDumpPostPlacement : public NGraphDumpPass {
public:
NGraphDumpPostPlacement() : NGraphDumpPass("post_placement") {}
};
class NGraphDumpPostReWrite : public NGraphDumpPass {
public:
NGraphDumpPostReWrite() : NGraphDumpPass("post_rewrite") {}
};
NGraphDumpPass
/src/ngraph_graph_rewrite_passes.cc
class NGraphDumpPostClustering : public NGraphDumpPass {
public:
NGraphDumpPostClustering() : NGraphDumpPass("post_clustering") {}
};
class NGraphDumpPostEncapsulation : public NGraphDumpPass {
public:
NGraphDumpPostEncapsulation() : NGraphDumpPass("post_encapsulation") {}
};
class NGraphDumpPostPartitioning : public NGraphDumpPass {
public:
NGraphDumpPostPartitioning() : NGraphDumpPass("post_partitioning") {}
};
NGraphDumpPass
Ops
src/ngraph_encapsulate_op.cc
REGISTER_OP("NGraphEncapsulate")
.Input("args: Targuments")
.Attr("Targuments: list(type) >= 0")
.Output("results: Tresults")
.Attr("Tresults: list(type) >= 0")
.Attr("ngraph_cluster: int")
.SetIsStateful()
.Doc("nGraph Encapsulation Op. For use by the nGraph JIT only.");
REGISTER_KERNEL_BUILDER(
Name("NGraphEncapsulate").Device(ngraph_bridge::DEVICE_NGRAPH),
ngraph_bridge::NGraphEncapsulateOp);
NGraphEncapsulateOp
src/ngraph_encapsulate_op.cc
NGraphEncapsulateOp(tf::OpKernelConstruction* ctx)
: tf::OpKernel(ctx), m_graph(tf::OpRegistry::Global()), m_freshness_tracker(nullptr) {
tf::GraphDef* graph_def;
OP_REQUIRES_OK(ctx, ctx->GetAttr<int>("ngraph_cluster", &m_ngraph_cluster));
// ここで、対応する Op の ctxから対応する GraphDef を獲得する
graph_def = NGraphClusterManager::GetClusterGraph(m_ngraph_cluster);
tf::GraphConstructorOptions opts;
opts.allow_internal_ops = true;
// GraphDef => Graphに変換
OP_REQUIRES_OK(ctx, tf::ConvertGraphDefToGraph(opts, *graph_def, &m_graph));
NGraphEncapsulateOp
src/ngraph_encapsulate_op.cc
// Create the backend
if (m_cpu_backend == nullptr) {
// 事前にバックエンドが指定されていないときは、 nGraphのCPUを使う
m_cpu_backend = ng::runtime::Backend::create("CPU");
OP_REQUIRES(ctx, m_cpu_backend != nullptr,
tf::errors::InvalidArgument("Cannot create CPU backend"));
}
}
NGraphEncapsulateOp
src/ngraph_encapsulate_pass.cc
void Compute(tf::OpKernelContext* ctx) override {
…..
// Compile the graph using nGraph.
//
// TODO(amprocte): Investigate performance of the compilation cache.
// 最初だけ、コンパイルする
// グラフ : m_graph => 関数 : ng_function
if (it == m_ng_functions.end()) {
OP_REQUIRES_OK(
ctx, Builder::TranslateGraph(input_shapes, &m_graph, ng_function));
…..
NGraphEncapsulateOp::Compute
src/ngraph_encapsulate_pass.cc
// Execute the nGraph function.
NGRAPH_VLOG(4) << "call starting for cluster " << m_ngraph_cluster;
// nGraphのバックエンドを使って、ng_function を実行する!
m_cpu_backend->call(ng_function, outputs, ng_inputs);
NGRAPH_VLOG(4) << "call done for cluster " << m_ngraph_cluster;
NGraphEncapsulateOp::Compute
src/ngraph_builder.cc
tf::Status Builder::TranslateGraph(
const std::vector<tf::TensorShape>& inputs,
const tf::Graph* input_graph,
shared_ptr<ng::Function>& ng_function)
// TensorFlow のグラフを nGraphのグラフ に変換し、nGraphでJIT後、
// ng_function (関数のポインタ) を返す
// この関数は、めっちゃ巨大ですよ
Builder::TranslateGraph
src/ngraph_builder.cc
vector<tf::Node*> tf_params;
vector<tf::Node*> tf_ret_vals;
vector<tf::Node*> tf_ops;
for (auto n : ordered) {
if (n->IsSink() || n->IsSource()) {
continue;
}
if (n->type_string() == "_Arg") {
tf_params.push_back(n); // パラメータ部
} else if (n->type_string() == "_Retval") {
tf_ret_vals.push_back(n); // 出力部
} else {
tf_ops.push_back(n);
}
}
Builder::TranslateGraph
src/ngraph_builder.cc
// パラメータ部
Builder::OpMap ng_op_map;
vector<shared_ptr<ng::op::Parameter>> ng_parameter_list(tf_params.size());
for (auto parm : tf_params) {
tf::DataType dtype = tf::GetNodeAttr(parm->attrs(), "T", &dtype);
int index = tf::GetNodeAttr(parm->attrs(), "index", &index);
ng::element::Type ng_et = TFDataTypeToNGraphElementType(dtype, &ng_et));
ng::Shape ng_shape = TFTensorShapeToNGraphShape(inputs[index], &ng_shape);
auto ng_param = make_shared<ng::op::Parameter>(ng_et, ng_shape);
ng_op_map[parm->name()] = ng_param;
ng_parameter_list[index] = ng_param;
}
Builder::TranslateGraph
src/ngraph_builder.cc
// 出力部
vector<shared_ptr<ng::Node>> ng_result_list(tf_ret_vals.size());
for (auto n : tf_ret_vals) {
tf::Node* tf_input_node;
n->input_node(0, &tf_input_node;
int index;
tf::GetNodeAttr(n->attrs(), "index", &index);
auto item = ng_op_map.find(tf_input_node->name());
if (item != ng_op_map.end()) {
ng_result_list[index] = item->second;
} else {
return tf::errors::InvalidArgument("Cannot find return node: ",
tf_input_node->name());
}
}
Builder::TranslateGraph
src/ngraph_builder.cc
vector<shared_ptr<ng::Node>> ng_result_list(tf_ret_vals.size());
for (auto n : tf_ret_vals) {
tf::Node* tf_input_node;
n->input_node(0, &tf_input_node);
int index;
tf::GetNodeAttr(n->attrs(), "index", &index);
auto item = ng_op_map.find(tf_input_node->name());
if (item != ng_op_map.end()) {
ng_result_list[index] = item->second;
}
// 関数のポインタ (nGraph)
ng_function = make_shared<ng::Function>(ng_result_list, ng_parameter_list);
return tf::Status::OK();
}
Builder::TranslateGraph
src/ngraph_builder.cc
// Now create the nGraph ops from TensorFlow ops.
//
for (auto op : tf_ops) {
NGRAPH_VLOG(2) << "Constructing op " << op->name() << " which is "
<< op->type_string();
// NOTE: The following cases should be kept in alphabetical order.
// いろいろな Ops に対する処理をしている
}
Builder::TranslateGraphでサポートするOps
src/ngraph_builder.cc
Abs, Add, AvgPool,
BiasAdd,
Cast, ConcatV2, Const, Conv2D,
DepthwiseConv2dNative,
Equal, Exp, ExpandDims,
Fill, Floor, FusedBatchNorm,
Greater, GreaterEqual,
Identify,
Less,LessEqual, Log, LogicalAnd,
MatMul, Maximum, MaxPool, Mean, Mul,
NoOp,
Pad, Pow, Prod,
Relu, Relu6, Reshape,
Sigmoid, Sign, Slice, Snapshot, Softmax, Sqeeze, StridedSlice, Sub, Sum,
TanH, Transpose,
Builder::TranslateGraphでサポートするOps
src/ngraph_stub_ops.cc
class NGraphStubOp : public OpKernel {
public:
explicit NGraphStubOp(OpKernelConstruction* ctx) : OpKernel(ctx) {}
void Compute(OpKernelContext* ctx) override {
OP_REQUIRES(ctx, false,
errors::Internal("NGraphStubOp compute kernel called"));
}
};
#define REGISTER_NGRAPH_STUB(name) 
REGISTER_KERNEL_BUILDER( 
Name(name).Device(ngraph_bridge::DEVICE_NGRAPH).Label("ngraph"), 
NGraphStubOp);
NGraphStubOp
src/ngraph_stub_ops.cc
REGISTER_NGRAPH_STUB("Abs");
REGISTER_NGRAPH_STUB("Add");
REGISTER_NGRAPH_STUB("AvgPool");
REGISTER_NGRAPH_STUB("BatchMatMul");
REGISTER_NGRAPH_STUB("BiasAdd");
REGISTER_NGRAPH_STUB("Cast");
REGISTER_NGRAPH_STUB("ConcatV2");
REGISTER_NGRAPH_STUB("Conv2D");
REGISTER_NGRAPH_STUB("Conv2DBackpropInput");
REGISTER_NGRAPH_STUB("DepthwiseConv2dNative");
REGISTER_NGRAPH_STUB("Equal");
REGISTER_NGRAPH_STUB("Exp");
REGISTER_NGRAPH_STUB("ExpandDims");
REGISTER_NGRAPH_STUB("Fill")
REGISTER_NGRAPH_STUB("Floor");
REGISTER_NGRAPH_STUB("MatMul");
REGISTER_NGRAPH_STUB("Maximum");
NGraphStubOp
src/ngraph_stub_ops.cc
REGISTER_NGRAPH_STUB("Minimum");
REGISTER_NGRAPH_STUB("Mul");
REGISTER_NGRAPH_STUB("Pack");
REGISTER_NGRAPH_STUB("Pad");
REGISTER_NGRAPH_STUB("Pow");
REGISTER_NGRAPH_STUB("Prod");
REGISTER_NGRAPH_STUB("RealDiv");
REGISTER_NGRAPH_STUB("Relu");
REGISTER_NGRAPH_STUB("Relu6");
REGISTER_NGRAPH_STUB("Reshape");
REGISTER_NGRAPH_STUB("Rsqrt");
REGISTER_NGRAPH_STUB("Slice");
REGISTER_NGRAPH_STUB("Sign");
REGISTER_NGRAPH_STUB("Sigmoid");
REGISTER_NGRAPH_STUB("Softmax");
REGISTER_NGRAPH_STUB("Snapshot");
NGraphStubOp
src/ngraph_stub_ops.cc
REGISTER_NGRAPH_STUB("Square");
REGISTER_NGRAPH_STUB("SquaredDifference");
REGISTER_NGRAPH_STUB("Squeeze");
REGISTER_NGRAPH_STUB("StridedSlice");
REGISTER_NGRAPH_STUB("Sub");
REGISTER_NGRAPH_STUB("Sum");
REGISTER_NGRAPH_STUB("Tanh");
REGISTER_NGRAPH_STUB("Tile");
REGISTER_NGRAPH_STUB("Transpose");
NGraphStubOp
src/ngraph_send_recv_ops.cc
REGISTER_KERNEL_BUILDER(Name("_Recv").Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphRecv);
REGISTER_KERNEL_BUILDER(Name("_Send").Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphSend);
REGISTER_KERNEL_BUILDER(
Name("_HostRecv").Device(ngraph_bridge::DEVICE_NGRAPH).HostMemory("tensor"),
NGraphRecv);
REGISTER_KERNEL_BUILDER(
Name("_HostSend").Device(ngraph_bridge::DEVICE_NGRAPH).HostMemory("tensor"),
NGraphSend);
NGraphRecv/NGraphSend
src/ngraph_send_recv_ops.cc
class NGraphRecv : public AsyncOpKernel {
public:
explicit NGraphRecv(OpKernelConstruction* ctx) {}
void ComputeAsync(OpKernelContext* ctx, DoneCallback done) override {}
private:
string key_prefix_;
tf::Rendezvous::ParsedKey parsed_key_;
bool hostmem_sendrecv_;
};
NGraphRecv
src/ngraph_send_recv_ops.cc
class NGraphSend : public OpKernel {
public:
explicit NGraphSend(OpKernelConstruction* ctx) : OpKernel(ctx):
void Compute(OpKernelContext* ctx) override;
private:
string key_prefix_;
tf::Rendezvous::ParsedKey parsed_key_;
bool hostmem_sendrecv_;
}
NGraphSend
と、説明しましたが、
Switch to deviceless (#117)
Large PR ("never again", I tell myself) to implement "deviceless" support for
nGraph. To make a long story short:
* The `NGRAPH` device goes away.
* `NGraphEncapsulateOp` now runs on the `CPU` device (no more sends/recvs)
* No more stub kernels or copied implementations of TF core ops like `Enter`/`Exit`
* Clustering, encapsulation, etc. is moved to an all-at-once pass in
`POST_REWRITE_FOR_EXEC` (so the weirdness we've seen where a confirmed
op gets rewritten without required attributes will not happen anymore).
https://github.com/NervanaSystems/ngraph-tf/commit/ddba671ba
23dda4e4e0f6e045936e05a624bb962
ブログ (2007年~) : Vengineerの戯言
 http://blogs.yahoo.co.jp/verification_engineer
SlideShare :
 https://www.slideshare.net/ssuser479fa3
Twitter (2009年~) :
@Vengineer
ありがとうございました
おまけ
src/ngraph_builder.h
class Builder {
public:
static tf::Status TranslateGraph(
const std::vector<tf::TensorShape>& inputs,
const tf::Graph* tf_graph,
shared_ptr<ng::Function>& ng_function);
using OpMap = unordered_map<string, shared_ptr<ng::Node>>;
};
tf::Status Builder::TranslateGraph(
const std::vector<tf::TensorShape>& inputs,
const tf::Graph* input_graph,
shared_ptr<ng::Function>& ng_function) {
…..
Builder::OpMap ng_op_map;
….
ng_op_map
src/ngraph_cluster.cc
const std::set<std::string> NGraphClusterPass::s_unclusterable_ops{
"Assign",
"Enter",
"Exit",
"IsVariableInitialized",
"Merge",
"NextIteration",
"Switch",
"VariableV2",
};
nGraphs Ops
src/ngraph_op_kernels.cc
REGISTER_KERNEL_BUILDER(
Name("Enter")
.Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphEnterOp);
REGISTER_KERNEL_BUILDER(
Name("Exit")
.Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphExitOp);
nGraphs Ops
src/ngraph_op_kernels.cc
REGISTER_KERNEL_BUILDER(
Name("NextIteration")
.Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphNextIterationOp);
REGISTER_KERNEL_BUILDER(
Name("Merge")
.Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphMergeOp);
REGISTER_KERNEL_BUILDER(
Name("Switch")
.Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphSwitchOp);
nGraphs Ops
src/ngraph_variable_ops.cc
REGISTER_KERNEL_BUILDER(
Name("VariableV2").Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphVariableOp);
REGISTER_KERNEL_BUILDER(
Name("Assign").Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphAssignOp);
REGISTER_KERNEL_BUILDER(
Name("IsVariableInitialized").Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphIsVariableInitializedOp);
nGraphs Ops
src/ngraph_cluster.cc
const std::set<std::string> NGraphClusterPass::s_can_be_outside_cluster_ops{
"Const",
"Identity",
"NoOp",
};
nGraphs Ops
src/ngraph_op_kernels.cc
REGISTER_KERNEL_BUILDER(Name("Const")
.Device(ngraph_bridge::DEVICE_NGRAPH)
.TypeConstraint("dtype", ngraph_bridge::NGraphDTypes()),
NGraphConstOp);
REGISTER_KERNEL_BUILDER(Name("Identity")
.Device(ngraph_bridge::DEVICE_NGRAPH)
.TypeConstraint("T", ngraph_bridge::NGraphDTypes()),
NGraphIdentityOp);
REGISTER_KERNEL_BUILDER(Name("NoOp")
.Device(ngraph_bridge::DEVICE_NGRAPH),
NGraphNoOp);
nGraphs Ops

More Related Content

What's hot

Architecture for Massively Parallel HDL Simulations
Architecture for Massively Parallel HDL Simulations Architecture for Massively Parallel HDL Simulations
Architecture for Massively Parallel HDL Simulations DVClub
 
Global Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the SealGlobal Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the SealTzung-Bi Shih
 
Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Sergey Platonov
 
Intel Nervana Graph とは?
Intel Nervana Graph とは?Intel Nervana Graph とは?
Intel Nervana Graph とは?Mr. Vengineer
 
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itEvgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itSergey Platonov
 
TensorFlow Lite (r1.5) & Android 8.1 Neural Network API
TensorFlow Lite (r1.5) & Android 8.1 Neural Network APITensorFlow Lite (r1.5) & Android 8.1 Neural Network API
TensorFlow Lite (r1.5) & Android 8.1 Neural Network APIMr. Vengineer
 
Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。Mr. Vengineer
 
C++ How I learned to stop worrying and love metaprogramming
C++ How I learned to stop worrying and love metaprogrammingC++ How I learned to stop worrying and love metaprogramming
C++ How I learned to stop worrying and love metaprogrammingcppfrug
 
Windbg랑 친해지기
Windbg랑 친해지기Windbg랑 친해지기
Windbg랑 친해지기Ji Hun Kim
 
Fuzzing: The New Unit Testing
Fuzzing: The New Unit TestingFuzzing: The New Unit Testing
Fuzzing: The New Unit TestingDmitry Vyukov
 
不深不淺,帶你認識 LLVM (Found LLVM in your life)
不深不淺,帶你認識 LLVM (Found LLVM in your life)不深不淺,帶你認識 LLVM (Found LLVM in your life)
不深不淺,帶你認識 LLVM (Found LLVM in your life)Douglas Chen
 
Алексей Кутумов, Coroutines everywhere
Алексей Кутумов, Coroutines everywhereАлексей Кутумов, Coroutines everywhere
Алексей Кутумов, Coroutines everywhereSergey Platonov
 
Deep Dive async/await in Unity with UniTask(EN)
Deep Dive async/await in Unity with UniTask(EN)Deep Dive async/await in Unity with UniTask(EN)
Deep Dive async/await in Unity with UniTask(EN)Yoshifumi Kawai
 
4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)
4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)
4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)PROIDEA
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?Doug Hawkins
 

What's hot (20)

Clang tidy
Clang tidyClang tidy
Clang tidy
 
Architecture for Massively Parallel HDL Simulations
Architecture for Massively Parallel HDL Simulations Architecture for Massively Parallel HDL Simulations
Architecture for Massively Parallel HDL Simulations
 
Tiramisu概要
Tiramisu概要Tiramisu概要
Tiramisu概要
 
Global Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the SealGlobal Interpreter Lock: Episode I - Break the Seal
Global Interpreter Lock: Episode I - Break the Seal
 
Joel Falcou, Boost.SIMD
Joel Falcou, Boost.SIMDJoel Falcou, Boost.SIMD
Joel Falcou, Boost.SIMD
 
Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >
 
Intel Nervana Graph とは?
Intel Nervana Graph とは?Intel Nervana Graph とは?
Intel Nervana Graph とは?
 
C++17 now
C++17 nowC++17 now
C++17 now
 
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itEvgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
 
TensorFlow Lite (r1.5) & Android 8.1 Neural Network API
TensorFlow Lite (r1.5) & Android 8.1 Neural Network APITensorFlow Lite (r1.5) & Android 8.1 Neural Network API
TensorFlow Lite (r1.5) & Android 8.1 Neural Network API
 
Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。
 
Qt Rest Server
Qt Rest ServerQt Rest Server
Qt Rest Server
 
C++ How I learned to stop worrying and love metaprogramming
C++ How I learned to stop worrying and love metaprogrammingC++ How I learned to stop worrying and love metaprogramming
C++ How I learned to stop worrying and love metaprogramming
 
Windbg랑 친해지기
Windbg랑 친해지기Windbg랑 친해지기
Windbg랑 친해지기
 
Fuzzing: The New Unit Testing
Fuzzing: The New Unit TestingFuzzing: The New Unit Testing
Fuzzing: The New Unit Testing
 
不深不淺,帶你認識 LLVM (Found LLVM in your life)
不深不淺,帶你認識 LLVM (Found LLVM in your life)不深不淺,帶你認識 LLVM (Found LLVM in your life)
不深不淺,帶你認識 LLVM (Found LLVM in your life)
 
Алексей Кутумов, Coroutines everywhere
Алексей Кутумов, Coroutines everywhereАлексей Кутумов, Coroutines everywhere
Алексей Кутумов, Coroutines everywhere
 
Deep Dive async/await in Unity with UniTask(EN)
Deep Dive async/await in Unity with UniTask(EN)Deep Dive async/await in Unity with UniTask(EN)
Deep Dive async/await in Unity with UniTask(EN)
 
4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)
4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)
4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 

Similar to Bridge TensorFlow to run on Intel nGraph backends (v0.4)

How Does Kubernetes Build OpenAPI Specifications?
How Does Kubernetes Build OpenAPI Specifications?How Does Kubernetes Build OpenAPI Specifications?
How Does Kubernetes Build OpenAPI Specifications?reallavalamp
 
Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1상욱 송
 
Владимир Перепелица "Модули"
Владимир Перепелица "Модули"Владимир Перепелица "Модули"
Владимир Перепелица "Модули"Media Gorod
 
How Many Ohs? (An Integration Guide to Apex & Triple-o)
How Many Ohs? (An Integration Guide to Apex & Triple-o)How Many Ohs? (An Integration Guide to Apex & Triple-o)
How Many Ohs? (An Integration Guide to Apex & Triple-o)OPNFV
 
Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Sylvain Wallez
 
Extending functionality in nginx, with modules!
Extending functionality in nginx, with modules!Extending functionality in nginx, with modules!
Extending functionality in nginx, with modules!Trygve Vea
 
OMG Namespaces! | Raffaele Di Fazio
OMG Namespaces! | Raffaele Di FazioOMG Namespaces! | Raffaele Di Fazio
OMG Namespaces! | Raffaele Di FazioKCDItaly
 
Monitoring Kafka w/ Prometheus
Monitoring Kafka w/ PrometheusMonitoring Kafka w/ Prometheus
Monitoring Kafka w/ Prometheuskawamuray
 
Control your deployments with Capistrano
Control your deployments with CapistranoControl your deployments with Capistrano
Control your deployments with CapistranoRamazan K
 
Inside the JVM - Follow the white rabbit! / Breizh JUG
Inside the JVM - Follow the white rabbit! / Breizh JUGInside the JVM - Follow the white rabbit! / Breizh JUG
Inside the JVM - Follow the white rabbit! / Breizh JUGSylvain Wallez
 
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Carlos Sanchez
 
More on bpftrace for MariaDB DBAs and Developers - FOSDEM 2022 MariaDB Devroom
More on bpftrace for MariaDB DBAs and Developers - FOSDEM 2022 MariaDB DevroomMore on bpftrace for MariaDB DBAs and Developers - FOSDEM 2022 MariaDB Devroom
More on bpftrace for MariaDB DBAs and Developers - FOSDEM 2022 MariaDB DevroomValeriy Kravchuk
 
Php 5.6 From the Inside Out
Php 5.6 From the Inside OutPhp 5.6 From the Inside Out
Php 5.6 From the Inside OutFerenc Kovács
 
Nginx internals
Nginx internalsNginx internals
Nginx internalsliqiang xu
 
X64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 newX64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 newYiwei Ma
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
Optimize + Deploy Distributed Tensorflow, Spark, and Scikit-Learn Models on GPUs
Optimize + Deploy Distributed Tensorflow, Spark, and Scikit-Learn Models on GPUsOptimize + Deploy Distributed Tensorflow, Spark, and Scikit-Learn Models on GPUs
Optimize + Deploy Distributed Tensorflow, Spark, and Scikit-Learn Models on GPUsChris Fregly
 

Similar to Bridge TensorFlow to run on Intel nGraph backends (v0.4) (20)

How Does Kubernetes Build OpenAPI Specifications?
How Does Kubernetes Build OpenAPI Specifications?How Does Kubernetes Build OpenAPI Specifications?
How Does Kubernetes Build OpenAPI Specifications?
 
Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1
 
Владимир Перепелица "Модули"
Владимир Перепелица "Модули"Владимир Перепелица "Модули"
Владимир Перепелица "Модули"
 
Amazon elastic map reduce
Amazon elastic map reduceAmazon elastic map reduce
Amazon elastic map reduce
 
How Many Ohs? (An Integration Guide to Apex & Triple-o)
How Many Ohs? (An Integration Guide to Apex & Triple-o)How Many Ohs? (An Integration Guide to Apex & Triple-o)
How Many Ohs? (An Integration Guide to Apex & Triple-o)
 
Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!
 
Extending functionality in nginx, with modules!
Extending functionality in nginx, with modules!Extending functionality in nginx, with modules!
Extending functionality in nginx, with modules!
 
OMG Namespaces! | Raffaele Di Fazio
OMG Namespaces! | Raffaele Di FazioOMG Namespaces! | Raffaele Di Fazio
OMG Namespaces! | Raffaele Di Fazio
 
Writing Nginx Modules
Writing Nginx ModulesWriting Nginx Modules
Writing Nginx Modules
 
Monitoring Kafka w/ Prometheus
Monitoring Kafka w/ PrometheusMonitoring Kafka w/ Prometheus
Monitoring Kafka w/ Prometheus
 
Control your deployments with Capistrano
Control your deployments with CapistranoControl your deployments with Capistrano
Control your deployments with Capistrano
 
Inside the JVM - Follow the white rabbit! / Breizh JUG
Inside the JVM - Follow the white rabbit! / Breizh JUGInside the JVM - Follow the white rabbit! / Breizh JUG
Inside the JVM - Follow the white rabbit! / Breizh JUG
 
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
 
More on bpftrace for MariaDB DBAs and Developers - FOSDEM 2022 MariaDB Devroom
More on bpftrace for MariaDB DBAs and Developers - FOSDEM 2022 MariaDB DevroomMore on bpftrace for MariaDB DBAs and Developers - FOSDEM 2022 MariaDB Devroom
More on bpftrace for MariaDB DBAs and Developers - FOSDEM 2022 MariaDB Devroom
 
Php 5.6 From the Inside Out
Php 5.6 From the Inside OutPhp 5.6 From the Inside Out
Php 5.6 From the Inside Out
 
Railsconf
RailsconfRailsconf
Railsconf
 
Nginx internals
Nginx internalsNginx internals
Nginx internals
 
X64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 newX64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 new
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
Optimize + Deploy Distributed Tensorflow, Spark, and Scikit-Learn Models on GPUs
Optimize + Deploy Distributed Tensorflow, Spark, and Scikit-Learn Models on GPUsOptimize + Deploy Distributed Tensorflow, Spark, and Scikit-Learn Models on GPUs
Optimize + Deploy Distributed Tensorflow, Spark, and Scikit-Learn Models on GPUs
 

More from Mr. Vengineer

XilinxのxsimでSoftware Driven Verification.pdf
XilinxのxsimでSoftware  Driven Verification.pdfXilinxのxsimでSoftware  Driven Verification.pdf
XilinxのxsimでSoftware Driven Verification.pdfMr. Vengineer
 
VerilatorとSystemCでSoftware Driven Verification
VerilatorとSystemCでSoftware Driven VerificationVerilatorとSystemCでSoftware Driven Verification
VerilatorとSystemCでSoftware Driven VerificationMr. Vengineer
 
Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析Mr. Vengineer
 
Cloud Deep Learning Chips Training & Inference
Cloud Deep Learning Chips Training & InferenceCloud Deep Learning Chips Training & Inference
Cloud Deep Learning Chips Training & InferenceMr. Vengineer
 
TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?Mr. Vengineer
 
Pixel Visual Core device driver source code analysis
Pixel Visual Core device driver source code analysisPixel Visual Core device driver source code analysis
Pixel Visual Core device driver source code analysisMr. Vengineer
 
TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」Mr. Vengineer
 
Ultra96(UltraZed)実践勉強会
Ultra96(UltraZed)実践勉強会Ultra96(UltraZed)実践勉強会
Ultra96(UltraZed)実践勉強会Mr. Vengineer
 
LeFlowを調べてみました
LeFlowを調べてみましたLeFlowを調べてみました
LeFlowを調べてみましたMr. Vengineer
 
Tensorflow dynamically loadable XLA plugin ソースコード解析
Tensorflow  dynamically loadable XLA plugin ソースコード解析Tensorflow  dynamically loadable XLA plugin ソースコード解析
Tensorflow dynamically loadable XLA plugin ソースコード解析Mr. Vengineer
 
「ディープラーニングでは、エコシステムが大切よ!」
 「ディープラーニングでは、エコシステムが大切よ!」 「ディープラーニングでは、エコシステムが大切よ!」
「ディープラーニングでは、エコシステムが大切よ!」Mr. Vengineer
 
TensorFlow XLA とハードウェア
TensorFlow XLA とハードウェアTensorFlow XLA とハードウェア
TensorFlow XLA とハードウェアMr. Vengineer
 
2017年のFPGA Community活動について
2017年のFPGA Community活動について2017年のFPGA Community活動について
2017年のFPGA Community活動についてMr. Vengineer
 
Zynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチZynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチMr. Vengineer
 
TensorFlow XLAの可能性
TensorFlow XLAの可能性 TensorFlow XLAの可能性
TensorFlow XLAの可能性 Mr. Vengineer
 
AWS EC2 F1とXilinx SDAccel
AWS EC2 F1とXilinx SDAccelAWS EC2 F1とXilinx SDAccel
AWS EC2 F1とXilinx SDAccelMr. Vengineer
 
DSPでディープラーニング
DSPでディープラーニングDSPでディープラーニング
DSPでディープラーニングMr. Vengineer
 
TensorFlow XLAは、 中で何をやっているのか?
TensorFlow XLAは、 中で何をやっているのか?TensorFlow XLAは、 中で何をやっているのか?
TensorFlow XLAは、 中で何をやっているのか?Mr. Vengineer
 

More from Mr. Vengineer (19)

XilinxのxsimでSoftware Driven Verification.pdf
XilinxのxsimでSoftware  Driven Verification.pdfXilinxのxsimでSoftware  Driven Verification.pdf
XilinxのxsimでSoftware Driven Verification.pdf
 
VerilatorとSystemCでSoftware Driven Verification
VerilatorとSystemCでSoftware Driven VerificationVerilatorとSystemCでSoftware Driven Verification
VerilatorとSystemCでSoftware Driven Verification
 
VerilatorとSystemC
VerilatorとSystemCVerilatorとSystemC
VerilatorとSystemC
 
Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析
 
Cloud Deep Learning Chips Training & Inference
Cloud Deep Learning Chips Training & InferenceCloud Deep Learning Chips Training & Inference
Cloud Deep Learning Chips Training & Inference
 
TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?
 
Pixel Visual Core device driver source code analysis
Pixel Visual Core device driver source code analysisPixel Visual Core device driver source code analysis
Pixel Visual Core device driver source code analysis
 
TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」
 
Ultra96(UltraZed)実践勉強会
Ultra96(UltraZed)実践勉強会Ultra96(UltraZed)実践勉強会
Ultra96(UltraZed)実践勉強会
 
LeFlowを調べてみました
LeFlowを調べてみましたLeFlowを調べてみました
LeFlowを調べてみました
 
Tensorflow dynamically loadable XLA plugin ソースコード解析
Tensorflow  dynamically loadable XLA plugin ソースコード解析Tensorflow  dynamically loadable XLA plugin ソースコード解析
Tensorflow dynamically loadable XLA plugin ソースコード解析
 
「ディープラーニングでは、エコシステムが大切よ!」
 「ディープラーニングでは、エコシステムが大切よ!」 「ディープラーニングでは、エコシステムが大切よ!」
「ディープラーニングでは、エコシステムが大切よ!」
 
TensorFlow XLA とハードウェア
TensorFlow XLA とハードウェアTensorFlow XLA とハードウェア
TensorFlow XLA とハードウェア
 
2017年のFPGA Community活動について
2017年のFPGA Community活動について2017年のFPGA Community活動について
2017年のFPGA Community活動について
 
Zynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチZynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチ
 
TensorFlow XLAの可能性
TensorFlow XLAの可能性 TensorFlow XLAの可能性
TensorFlow XLAの可能性
 
AWS EC2 F1とXilinx SDAccel
AWS EC2 F1とXilinx SDAccelAWS EC2 F1とXilinx SDAccel
AWS EC2 F1とXilinx SDAccel
 
DSPでディープラーニング
DSPでディープラーニングDSPでディープラーニング
DSPでディープラーニング
 
TensorFlow XLAは、 中で何をやっているのか?
TensorFlow XLAは、 中で何をやっているのか?TensorFlow XLAは、 中で何をやっているのか?
TensorFlow XLAは、 中で何をやっているのか?
 

Recently uploaded

Vibration of Continuous Systems.pjjjjjjjjptx
Vibration of Continuous Systems.pjjjjjjjjptxVibration of Continuous Systems.pjjjjjjjjptx
Vibration of Continuous Systems.pjjjjjjjjptxjoshuaclack73
 
办理(uw学位证书)美国华盛顿大学毕业证续费收据一模一样
办理(uw学位证书)美国华盛顿大学毕业证续费收据一模一样办理(uw学位证书)美国华盛顿大学毕业证续费收据一模一样
办理(uw学位证书)美国华盛顿大学毕业证续费收据一模一样vwymvu
 
如何办理(AUT毕业证书)奥克兰理工大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(AUT毕业证书)奥克兰理工大学毕业证成绩单本科硕士学位证留信学历认证如何办理(AUT毕业证书)奥克兰理工大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(AUT毕业证书)奥克兰理工大学毕业证成绩单本科硕士学位证留信学历认证mestb
 
Abortion pills in Jeddah +966572737505 <> buy cytotec <> unwanted kit Saudi A...
Abortion pills in Jeddah +966572737505 <> buy cytotec <> unwanted kit Saudi A...Abortion pills in Jeddah +966572737505 <> buy cytotec <> unwanted kit Saudi A...
Abortion pills in Jeddah +966572737505 <> buy cytotec <> unwanted kit Saudi A...samsungultra782445
 
Jual Obat Aborsi Samarinda ( No.1 ) 088980685493 Obat Penggugur Kandungan Cy...
Jual Obat Aborsi Samarinda (  No.1 ) 088980685493 Obat Penggugur Kandungan Cy...Jual Obat Aborsi Samarinda (  No.1 ) 088980685493 Obat Penggugur Kandungan Cy...
Jual Obat Aborsi Samarinda ( No.1 ) 088980685493 Obat Penggugur Kandungan Cy...Obat Aborsi 088980685493 Jual Obat Aborsi
 
一比一原版(Otago毕业证书)奥塔哥理工学院毕业证成绩单学位证靠谱定制
一比一原版(Otago毕业证书)奥塔哥理工学院毕业证成绩单学位证靠谱定制一比一原版(Otago毕业证书)奥塔哥理工学院毕业证成绩单学位证靠谱定制
一比一原版(Otago毕业证书)奥塔哥理工学院毕业证成绩单学位证靠谱定制uodye
 
Matrix Methods.pptxhhhhhhhhhhhhhhhhhhhhh
Matrix Methods.pptxhhhhhhhhhhhhhhhhhhhhhMatrix Methods.pptxhhhhhhhhhhhhhhhhhhhhh
Matrix Methods.pptxhhhhhhhhhhhhhhhhhhhhhjoshuaclack73
 
在线制作(ANU毕业证书)澳大利亚国立大学毕业证成绩单原版一比一
在线制作(ANU毕业证书)澳大利亚国立大学毕业证成绩单原版一比一在线制作(ANU毕业证书)澳大利亚国立大学毕业证成绩单原版一比一
在线制作(ANU毕业证书)澳大利亚国立大学毕业证成绩单原版一比一ougvy
 
如何办理(UVic毕业证书)维多利亚大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(UVic毕业证书)维多利亚大学毕业证成绩单本科硕士学位证留信学历认证如何办理(UVic毕业证书)维多利亚大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(UVic毕业证书)维多利亚大学毕业证成绩单本科硕士学位证留信学历认证mestb
 
Mahindra XUV new version for smooth travelling
Mahindra XUV new version for smooth travellingMahindra XUV new version for smooth travelling
Mahindra XUV new version for smooth travellingSailaja Gudipati
 
NON INVASIVE GLUCOSE BLODD MONITORING SYSTEM (1) (2) (1).pptx
NON INVASIVE GLUCOSE BLODD MONITORING SYSTEM (1) (2) (1).pptxNON INVASIVE GLUCOSE BLODD MONITORING SYSTEM (1) (2) (1).pptx
NON INVASIVE GLUCOSE BLODD MONITORING SYSTEM (1) (2) (1).pptxSimmySharma12
 
在线办理(scu毕业证)南十字星大学毕业证电子版学位证书注册证明信
在线办理(scu毕业证)南十字星大学毕业证电子版学位证书注册证明信在线办理(scu毕业证)南十字星大学毕业证电子版学位证书注册证明信
在线办理(scu毕业证)南十字星大学毕业证电子版学位证书注册证明信oopacde
 
一比一原版(LaTrobe毕业证书)澳洲拉筹伯大学毕业证学位证书
一比一原版(LaTrobe毕业证书)澳洲拉筹伯大学毕业证学位证书一比一原版(LaTrobe毕业证书)澳洲拉筹伯大学毕业证学位证书
一比一原版(LaTrobe毕业证书)澳洲拉筹伯大学毕业证学位证书ougvy
 
一比一维多利亚大学毕业证(victoria毕业证)成绩单学位证如何办理
一比一维多利亚大学毕业证(victoria毕业证)成绩单学位证如何办理一比一维多利亚大学毕业证(victoria毕业证)成绩单学位证如何办理
一比一维多利亚大学毕业证(victoria毕业证)成绩单学位证如何办理uodye
 
Test bank for consumer behaviour buying having and being eighth canadian edit...
Test bank for consumer behaviour buying having and being eighth canadian edit...Test bank for consumer behaviour buying having and being eighth canadian edit...
Test bank for consumer behaviour buying having and being eighth canadian edit...robinsonayot
 
在线制作(UQ毕业证书)昆士兰大学毕业证成绩单原版一比一
在线制作(UQ毕业证书)昆士兰大学毕业证成绩单原版一比一在线制作(UQ毕业证书)昆士兰大学毕业证成绩单原版一比一
在线制作(UQ毕业证书)昆士兰大学毕业证成绩单原版一比一uodye
 
如何办理(SUT毕业证书)斯威本科技大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(SUT毕业证书)斯威本科技大学毕业证成绩单本科硕士学位证留信学历认证如何办理(SUT毕业证书)斯威本科技大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(SUT毕业证书)斯威本科技大学毕业证成绩单本科硕士学位证留信学历认证mestb
 

Recently uploaded (20)

Vibration of Continuous Systems.pjjjjjjjjptx
Vibration of Continuous Systems.pjjjjjjjjptxVibration of Continuous Systems.pjjjjjjjjptx
Vibration of Continuous Systems.pjjjjjjjjptx
 
Abortion pills in Riyadh Saudi Arabia!+966572737505 ) Where to get cytotec
Abortion pills in Riyadh Saudi Arabia!+966572737505 ) Where to get cytotecAbortion pills in Riyadh Saudi Arabia!+966572737505 ) Where to get cytotec
Abortion pills in Riyadh Saudi Arabia!+966572737505 ) Where to get cytotec
 
办理(uw学位证书)美国华盛顿大学毕业证续费收据一模一样
办理(uw学位证书)美国华盛顿大学毕业证续费收据一模一样办理(uw学位证书)美国华盛顿大学毕业证续费收据一模一样
办理(uw学位证书)美国华盛顿大学毕业证续费收据一模一样
 
如何办理(AUT毕业证书)奥克兰理工大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(AUT毕业证书)奥克兰理工大学毕业证成绩单本科硕士学位证留信学历认证如何办理(AUT毕业证书)奥克兰理工大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(AUT毕业证书)奥克兰理工大学毕业证成绩单本科硕士学位证留信学历认证
 
Abortion pills in Jeddah +966572737505 <> buy cytotec <> unwanted kit Saudi A...
Abortion pills in Jeddah +966572737505 <> buy cytotec <> unwanted kit Saudi A...Abortion pills in Jeddah +966572737505 <> buy cytotec <> unwanted kit Saudi A...
Abortion pills in Jeddah +966572737505 <> buy cytotec <> unwanted kit Saudi A...
 
Jual Obat Aborsi Samarinda ( No.1 ) 088980685493 Obat Penggugur Kandungan Cy...
Jual Obat Aborsi Samarinda (  No.1 ) 088980685493 Obat Penggugur Kandungan Cy...Jual Obat Aborsi Samarinda (  No.1 ) 088980685493 Obat Penggugur Kandungan Cy...
Jual Obat Aborsi Samarinda ( No.1 ) 088980685493 Obat Penggugur Kandungan Cy...
 
一比一原版(Otago毕业证书)奥塔哥理工学院毕业证成绩单学位证靠谱定制
一比一原版(Otago毕业证书)奥塔哥理工学院毕业证成绩单学位证靠谱定制一比一原版(Otago毕业证书)奥塔哥理工学院毕业证成绩单学位证靠谱定制
一比一原版(Otago毕业证书)奥塔哥理工学院毕业证成绩单学位证靠谱定制
 
Matrix Methods.pptxhhhhhhhhhhhhhhhhhhhhh
Matrix Methods.pptxhhhhhhhhhhhhhhhhhhhhhMatrix Methods.pptxhhhhhhhhhhhhhhhhhhhhh
Matrix Methods.pptxhhhhhhhhhhhhhhhhhhhhh
 
Contact +971581248768 to buy 100% original and safe abortion pills in Dubai a...
Contact +971581248768 to buy 100% original and safe abortion pills in Dubai a...Contact +971581248768 to buy 100% original and safe abortion pills in Dubai a...
Contact +971581248768 to buy 100% original and safe abortion pills in Dubai a...
 
在线制作(ANU毕业证书)澳大利亚国立大学毕业证成绩单原版一比一
在线制作(ANU毕业证书)澳大利亚国立大学毕业证成绩单原版一比一在线制作(ANU毕业证书)澳大利亚国立大学毕业证成绩单原版一比一
在线制作(ANU毕业证书)澳大利亚国立大学毕业证成绩单原版一比一
 
如何办理(UVic毕业证书)维多利亚大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(UVic毕业证书)维多利亚大学毕业证成绩单本科硕士学位证留信学历认证如何办理(UVic毕业证书)维多利亚大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(UVic毕业证书)维多利亚大学毕业证成绩单本科硕士学位证留信学历认证
 
Mahindra XUV new version for smooth travelling
Mahindra XUV new version for smooth travellingMahindra XUV new version for smooth travelling
Mahindra XUV new version for smooth travelling
 
Abortion pills in Jeddah Saudi Arabia! +966572737505 Where to buy cytotec
Abortion pills in Jeddah Saudi Arabia! +966572737505 Where to buy cytotecAbortion pills in Jeddah Saudi Arabia! +966572737505 Where to buy cytotec
Abortion pills in Jeddah Saudi Arabia! +966572737505 Where to buy cytotec
 
NON INVASIVE GLUCOSE BLODD MONITORING SYSTEM (1) (2) (1).pptx
NON INVASIVE GLUCOSE BLODD MONITORING SYSTEM (1) (2) (1).pptxNON INVASIVE GLUCOSE BLODD MONITORING SYSTEM (1) (2) (1).pptx
NON INVASIVE GLUCOSE BLODD MONITORING SYSTEM (1) (2) (1).pptx
 
在线办理(scu毕业证)南十字星大学毕业证电子版学位证书注册证明信
在线办理(scu毕业证)南十字星大学毕业证电子版学位证书注册证明信在线办理(scu毕业证)南十字星大学毕业证电子版学位证书注册证明信
在线办理(scu毕业证)南十字星大学毕业证电子版学位证书注册证明信
 
一比一原版(LaTrobe毕业证书)澳洲拉筹伯大学毕业证学位证书
一比一原版(LaTrobe毕业证书)澳洲拉筹伯大学毕业证学位证书一比一原版(LaTrobe毕业证书)澳洲拉筹伯大学毕业证学位证书
一比一原版(LaTrobe毕业证书)澳洲拉筹伯大学毕业证学位证书
 
一比一维多利亚大学毕业证(victoria毕业证)成绩单学位证如何办理
一比一维多利亚大学毕业证(victoria毕业证)成绩单学位证如何办理一比一维多利亚大学毕业证(victoria毕业证)成绩单学位证如何办理
一比一维多利亚大学毕业证(victoria毕业证)成绩单学位证如何办理
 
Test bank for consumer behaviour buying having and being eighth canadian edit...
Test bank for consumer behaviour buying having and being eighth canadian edit...Test bank for consumer behaviour buying having and being eighth canadian edit...
Test bank for consumer behaviour buying having and being eighth canadian edit...
 
在线制作(UQ毕业证书)昆士兰大学毕业证成绩单原版一比一
在线制作(UQ毕业证书)昆士兰大学毕业证成绩单原版一比一在线制作(UQ毕业证书)昆士兰大学毕业证成绩单原版一比一
在线制作(UQ毕业证书)昆士兰大学毕业证成绩单原版一比一
 
如何办理(SUT毕业证书)斯威本科技大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(SUT毕业证书)斯威本科技大学毕业证成绩单本科硕士学位证留信学历认证如何办理(SUT毕业证书)斯威本科技大学毕业证成绩单本科硕士学位证留信学历认证
如何办理(SUT毕业证书)斯威本科技大学毕业证成绩单本科硕士学位证留信学历认证
 

Bridge TensorFlow to run on Intel nGraph backends (v0.4)