-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Async GRPC sendrecv #7133
Async GRPC sendrecv #7133
Conversation
using grpc::ClientWriter; | ||
using grpc::Status; | ||
using sendrecv::SendRecvService; | ||
using sendrecv::VariableMessage; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't use C++ often, so I am likely to be wrong. I personally feel that:
void Run(const framework::Scope* scope, const std::string name,
sendrecv::VariableMessage* msg) {
is easier to understand than:
void Run(const framework::Scope* scope, const std::string name,
VariableMessage* msg) {
Since sendrecv::VariableMessage
tells us that VariableMessage
is from a different module, and that module does things like send and recv, so I can infer that VariableMessage
is the message used for send and recv.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.Thanks.
framework::DeserializeFromStream(iss, &ret_tensor); | ||
auto* outvar = scope->FindVar(name); | ||
framework::LoDTensor* out_tensor = | ||
outvar->GetMutable<framework::LoDTensor>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible that the variable type for send/recv is not framework::LoDTensor
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.Add FixME comments.
Done.
|
||
// Block until the next result is available | ||
// in the completion queue "cq". | ||
cq.Next(&which, &ok); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to check the value of ok
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.Thanks.
namespace operators { | ||
namespace detail { | ||
|
||
struct Var { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have Variable
, to avoid confusion, maybe change name to something like VarHandle
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
new RequestSend(service_, cq_); | ||
|
||
// The actual processing. | ||
// std::string prefix("Hello "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No commented out code please :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.Done.
service_->RequestSendVariable(&ctx_, &request_, &responder_, cq_, cq_, | ||
this); | ||
} else if (status_ == PROCESS) { | ||
new RequestSend(service_, cq_); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could not understand what does this code block do, why does it not use request_
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A detail comments is here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the status is not useful also. I'll test it later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我的理解:
- CREATE的时候注册消息处理的类。
- PROCESS的时候是完成队列通知request已经准备好,可以处理了。
- FINISH的时候是完成队列通知reply已经发送完了。
所以这个PROCEED从完成队列中重入两次。
namespace operators { | ||
namespace detail { | ||
|
||
enum CallStatus { CREATE, PROCESS, FINISH }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to understand what CREATE, PROCESS, FINISH does, but where are they used by the client?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A detail comments is here.
#include "grpc_client.h" | ||
#include <future> | ||
|
||
using grpc::Server; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unnecessary using lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
} | ||
}; | ||
|
||
class AsyncGRPCClient { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just call this class RPCClient
the same as before since we only use just one client and remove the previous implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
// is sent completely and don't wait all. | ||
protected: | ||
template <typename send_t, typename recv_t, typename Msg_t> | ||
bool Call(const framework::Scope* scope, const std::vector<Var>& in, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Call
has no meaning, change to some function names that mean something, please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
AsyncGRPCClient() {} | ||
|
||
void AddEndPoint(std::string ep); | ||
void AddEndPoint(const std::vector<std::string>& ep); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete AddEndPoint
, and put the initialization into two overloaded ctors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will refactor client interface.
const framework::Scope* scope, std::string name) {} | ||
|
||
template <typename send_t, typename recv_t> | ||
void Call(grpc::CompletionQueue* cq, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SendMsg
have Run
and Call
which is confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
responder_.Finish(reply_, Status::OK, this); | ||
} else { | ||
GPR_ASSERT(status_ == FINISH); | ||
delete this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete this
should be used very carefully or never use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will test later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete this
cause core down.
const time_point deadline = s.start + std::chrono::milliseconds(5000); | ||
|
||
// context | ||
ClientContext* context = new ClientContext(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use unique_ptr to avoid memory leak.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
already in.
}; | ||
|
||
template <typename send_t, typename recv_t, typename Msg_t> | ||
bool AsyncGRPCClient::Call(const framework::Scope* scope, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Templates should be placed at .h
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
} | ||
}; | ||
|
||
template <typename send_t, typename recv_t, typename Msg_t> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typenames should be capitalized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
typedef std::chrono::system_clock::time_point time_point; | ||
|
||
for (int64_t i = 0; i < (int64_t)in.size(); i++) { | ||
PADDLE_ENFORCE(channels_.find(in[i].endpoint) != channels_.end()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not manage channels in a single client, let the caller manage this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or you can write a multi-client class to do multi send.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Reconstruction grpc_client. |
@@ -1 +1 @@ | |||
grpc_library(sendrecvop_grpc SRCS recv_impl.cc send_impl.cc PROTO send_recv.proto DEPS lod_tensor selected_rows) | |||
grpc_library(sendrecvop_grpc SRCS recv_impl.cc send_impl.cc grpc_client.cc grpc_server.cc PROTO send_recv.proto DEPS lod_tensor selected_rows) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove recv_impl.cc
send_impl.cc
if they are nolonger used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.Thanks.
paddle/operators/send_op.cc
Outdated
// one tensor | ||
bool Send(const std::vector<std::string>& ep, const framework::Scope* scope, | ||
const std::vector<std::string>& ins, int64_t time_out) { | ||
detail::RPCClients c; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating new client object in each send is inefficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.Thanks.
SendStatus send_status_; | ||
}; | ||
|
||
class RPCClients { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still believe that send_op should be responsible to determine which endpoint should each variable send to. Client is only responsible for how to do communication, send_op is responsible for how to manage the send, if we are going to implement something like "ring-based all reduce", will only need to write a new send_op
and do not need to change this client implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.Thanks.
SendStatus GetSendStatus() { return send_status_; } | ||
|
||
private: | ||
void _Request(const framework::Scope* scope, const std::string name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.Thanks.
ch_ = ch; | ||
ep_ = ep; | ||
stub_ = sendrecv::SendRecvService::NewStub(ch); | ||
context_.reset(new grpc::ClientContext()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
context
should be created before every rpc send call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.Thanks.
} | ||
}; | ||
|
||
class ClientBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would an RPCClient implementing SendVariable
and GetVariable
be sufficient?
members are the same and send, get should be called on the same RPC client stub
+ std::shared_ptr<grpc::CompletionQueue> cq_;
+ std::shared_ptr<grpc::Channel> ch_;
+ std::string ep_;
+ std::unique_ptr<sendrecv::SendRecvService::Stub> stub_;
+ std::unique_ptr<grpc::ClientContext> context_;
+ std::unique_ptr<grpc::Status> status_;
+ std::unique_ptr<sendrecv::VoidMessage> reply_;
+ std::unique_ptr<grpc::ClientAsyncResponseReader<sendrecv::VoidMessage>> rpc_;
+ SendStatus send_status_;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.thanks.
#7161 add some features about send/recv op, so please fix the conflict first. |
bool wait(); | ||
|
||
private: | ||
bool Proceed(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By Proceed
do you mean Process
, proceed means go on with something. The sample code use proceed maybe because it's a stream request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
private: | ||
grpc::CompletionQueue cq_; | ||
std::map<std::string, std::shared_ptr<grpc::Channel>> channels_; | ||
int64_t count_ = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
count_
is a name with less information, use xxx_count_
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
public: | ||
bool AsyncSendVariable(const std::string& ep, | ||
const platform::DeviceContext& ctx, | ||
const framework::Scope* scope, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be const framework::Scope&
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
auto ch = GetChannel(ep); | ||
SendProcessor* s = new SendProcessor(ch); | ||
s->Prepare(var_h, time_out); | ||
s->response_call_back = ProcSendResponse; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since ProcSendResponse
is doing nothing, pass NULL
here should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
typedef std::function<void(const VarHandle&, const sendrecv::VoidMessage&)> | ||
RequestSendCallBack; | ||
|
||
struct SendProcessor : public ClientBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my point of view, thought below definition would be simpler to implement:
typedef void (*rpc_response_callback)(const framework::Scope&, void* message);
class RPCClient {
....
private:
struct RPCResponse {
rpc_response_callback callback_;
const framework::Scope& scope_;
std::string varname_;
int ret_msg_type_;
grpc::Status status_;
};
};
Then AsyncSendVariable
and AsyncGetVariable
can use ret_msg_type_
to get whether to cast message to VoidMessage
or VariableMessage
. VarHandle
can also be ommited.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then
AsyncSendVariable
andAsyncGetVariable
can useret_msg_type_
to get whether to cast message toVoidMessage
orVariableMessage
.
这个我试过了。需要暴露类型的变量有两个,这是不能用一个struct解决的。
sendrecv::XXXMessageType reply;
RequestXXXCallBack response_call_back
根据ret_msg_type_是不够的,不方便以后的扩展,而是应该根据action_type
来判断哪种操作类型。有两个问题
- 代码写起来很丑陋,需要各处switch。
2.扩展起来不方便。
异步的情况下:VarHandle
里边的信息还是有用的:
struct VarHandle {
std::string ep;
const platform::DeviceContext* ctx;
const framework::Scope& scope;
std::string name;
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要暴露类型的变量有两个,这是不能用一个struct解决的。
嗯。感觉这个也不是主要原因,从扩展来讲,用继承会比较好。
异步的情况下:VarHandle里边的信息还是有用的:
我理解应该是为了减少callback中的参数个数。这样的话,可以直接把callback定义成void(void* ret_msg, void* user_data)
,在不同的继承的Processor中再cast到实际的类型,扩展性会更好。
enum CallStatus { PROCESS = 0, FINISH }; | ||
|
||
// reference: | ||
// https://stackoverflow.com/questions/41732884/grpc-multiple-services-in-cpp-async-server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact we only have one service: service SendRecvService
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For more than two types of calls, you could achieve the same behavior with an enum instead of a bool.
A more flexible approach would be to have a different CallData-like class for each RPC. However when you get a tag from cq_->Next()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation, now I figure it out!
* https://stackoverflow.com/questions/35708348/grpc-what-is-the-recommended-way-to-shut-down-an-asynchronous-server-in-c | ||
*/ | ||
void AsyncGRPCServer::ShutDown() { | ||
ShutdownGetQueue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
paddle/operators/detail/utils.h
Outdated
namespace operators { | ||
namespace detail { | ||
|
||
void SerializeToMessage(const std::string& name, const framework::Variable* var, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please put these two function into grpc_client.h
, file name util.h
have less information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这样的话grpc_server.cc
需要依赖grpc_client.h
了。。。。
|
||
std::mutex cq_get_mutex_; | ||
mutable bool is_get_shut_down_ = false; | ||
std::unique_ptr<grpc::ServerCompletionQueue> cq_get_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can server-side use one single ServerCompletionQueue
? And two threads to deal with different message make this implement complicated. Since we have var_recv_queue_
so the backend can use multiple threads to deal with incoming requests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved in another way.Done.
@@ -1 +1 @@ | |||
grpc_library(sendrecvop_grpc SRCS recv_impl.cc send_impl.cc PROTO send_recv.proto DEPS lod_tensor selected_rows) | |||
grpc_library(sendrecvop_grpc SRCS utils.cc grpc_client.cc grpc_server.cc PROTO send_recv.proto DEPS lod_tensor selected_rows) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utils.cc
=> sendrecvop_utils
, I think it's not a common utils.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
// stub context | ||
auto ch = GetChannel(ep); | ||
SendProcessor* s = new SendProcessor(ch); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think std::unique_ptr<SendProcessor> s(new SendProcessor(ch));
is a better way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The memory should not be released and should transformed to Completion queue.
rpc->Finish(&s->reply, &s->status, (void*)s);
PADDLE_ENFORCE(tag); | ||
|
||
// TODO(gongwb): add more retries. | ||
ClientBase* c = (ClientBase*)tag; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ClientBase* c = (ClientBase*)tag
=>
ClientBase* c = static_cast<ClientBase *>(tag)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
virtual void Proceed() = 0; | ||
|
||
std::unique_ptr<sendrecv::SendRecvService::Stub> stub; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following https://google.github.io/styleguide/cppguide.html#Variable_Names, please add the underscore at end of the variable name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see Struct Data Members
section.
|
||
bool AsyncGetVariable(const std::string& ep, | ||
const platform::DeviceContext& ctx, | ||
const framework::Scope* scope, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The save as above
const framework::Scope* scope
=>
const framework::Scope& scope
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
explicit RequestBase(sendrecv::SendRecvService::AsyncService* service, | ||
grpc::ServerCompletionQueue* cq) | ||
: service_(service), cq_(cq) { | ||
status_ = PROCESS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move status_ = PROCESS
to the constructor initializer list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
// proc request. | ||
std::string var_name = request_.varname(); | ||
auto* var = scope_->FindVar(var_name); | ||
// FIXME(gongwb): device context? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can not understand what's the meaning of FIXME comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some tiny comments, can be merged soon!
void ProcGetResponse(const VarHandle& var_h, | ||
const sendrecv::VariableMessage& msg); | ||
|
||
struct ClientBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change to class
according to https://google.github.io/styleguide/cppguide.html#Structs_vs._Classes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
typedef std::function<void(const VarHandle&, const sendrecv::VoidMessage&)> | ||
RequestSendCallBack; | ||
|
||
struct SendProcessor : public ClientBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要暴露类型的变量有两个,这是不能用一个struct解决的。
嗯。感觉这个也不是主要原因,从扩展来讲,用继承会比较好。
异步的情况下:VarHandle里边的信息还是有用的:
我理解应该是为了减少callback中的参数个数。这样的话,可以直接把callback定义成void(void* ret_msg, void* user_data)
,在不同的继承的Processor中再cast到实际的类型,扩展性会更好。
enum CallStatus { PROCESS = 0, FINISH }; | ||
|
||
// reference: | ||
// https://stackoverflow.com/questions/41732884/grpc-multiple-services-in-cpp-async-server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation, now I figure it out!
virtual ~RequestSend() {} | ||
|
||
virtual void Process() { | ||
// proc request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove the comment line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
if (is_shut_down_) { | ||
return; | ||
} | ||
// base->RegisterNewOne(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove commented out code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
/* | ||
* This URL explains why shutdown is complicate: | ||
* https://stackoverflow.com/questions/35708348/grpc-what-is-the-recommended-way-to-shut-down-an-asynchronous-server-in-c | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
private: | ||
std::mutex cq_mutex_; | ||
mutable bool is_shut_down_ = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mutable
is for const functions, and there is no const functions?
break; | ||
} | ||
case FINISH: { | ||
VLOG(4) << cq_name << " status:" << base->Status(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the same VLOG
level in RPC implements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -136,11 +136,21 @@ void StartServerNet(bool is_sparse) { | |||
attrs.insert({"OptimizeProgram", program_proto}); | |||
recv_op = f::OpRegistry::CreateOp("recv", {{"RX", {"x1"}}}, {}, attrs); | |||
recv_op->Run(scope, place); | |||
|
|||
std::cout << "servernet end" << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unit test printing code.
@@ -138,9 +138,17 @@ void StartServerNet(bool is_sparse) { | |||
recv_op->Run(scope, place); | |||
} | |||
|
|||
void PrintTop(std::string name, float *data) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove printing in the unit test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这些print在出现错误的时候用来查找错误还是非常有用的。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ctest可以在错误的时候输出对比的数据。不需要print。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
只能看到一个,其实很不利于找到错误。
Done。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM++
Fix #7041