send_op.cc 3.1 KB
Newer Older
武毅 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
/* Copyright (c) 2016 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 <ostream>

#include "paddle/framework/data_type.h"
#include "paddle/framework/framework.pb.h"
#include "paddle/framework/lod_tensor.h"
#include "paddle/framework/op_registry.h"

#include "paddle/operators/detail/send_recv_impl.h"
#include "paddle/operators/detail/simple_block_queue.h"

namespace paddle {
namespace operators {

// TODO(typhoonzero): this is a simple implementation which only send
// one tensor
class SendOp : public framework::OperatorBase {
 public:
  SendOp(const std::string &type, const framework::VariableNameMap &inputs,
         const framework::VariableNameMap &outputs,
         const framework::AttributeMap &attrs)
      : OperatorBase(type, inputs, outputs, attrs) {
    // init client when the operator is created at runtime.
    if (!client_) {
      std::string endpoint = Attr<std::string>("endpoint");
      client_.reset(new detail::RPCClient(
          grpc::CreateChannel(endpoint, grpc::InsecureChannelCredentials())));
      // TODO(typhoonzero): how to call InitVariables
    }
  }
  void Run(const framework::Scope &scope,
           const platform::DeviceContext &dev_ctx) const override {
T
typhoonzero 已提交
46
    auto ins = Inputs("X");
武毅 已提交
47 48
    // TODO(typhoonzero): currently it's non-blocking,
    // should block until server responds.
T
typhoonzero 已提交
49
    for (auto in : ins) {
T
typhoonzero 已提交
50
      LOG(ERROR) << "sending grad: " << in;
T
typhoonzero 已提交
51
      bool ret = client_->SendVariable(scope, in);
T
typhoonzero 已提交
52 53 54
      if (!ret) {
        LOG(ERROR) << "send variable error";
      }
武毅 已提交
55
    }
T
typhoonzero 已提交
56 57 58 59 60 61 62
    for (auto in : ins) {
      LOG(ERROR) << "updating from server...";
      bool ret = client_->GetVariable(scope);
      if (!ret) {
        LOG(ERROR) << "GetVariable error";
      }
    }
武毅 已提交
63 64 65 66 67 68 69 70 71 72
  }

 protected:
  std::shared_ptr<detail::RPCClient> client_{nullptr};
};

class SendOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  SendOpMaker(framework::OpProto *proto, framework::OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
T
typhoonzero 已提交
73
    AddInput("X", "(Tensor) Input tensor to be send").AsDuplicable();
武毅 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    AddComment(R"DOC(
Recv operator

This operator will recv tensor from send_op
)DOC");
    AddAttr<std::string>("endpoint",
                         "(string, default 127.0.0.1:6164)"
                         "IP address to listen on.")
        .SetDefault("127.0.0.1:6164")
        .AddCustomChecker([](const std::string &ip) { return !ip.empty(); });
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

REGISTER_OPERATOR(send, ops::SendOp, ops::SendOpMaker);