-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
new parameterupdater use paddle pserver cclient of go #2413
new parameterupdater use paddle pserver cclient of go #2413
Conversation
* @param new_paras | ||
* @param type | ||
*/ | ||
void initNewParameter(paddle_parameter**& new_paras, ParameterType type) { |
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.
这个引用去掉是不是比较好?这里只是 *type,指针拷贝没有代价。这样写风格有点怪~
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.
initNewParameter
seems only called inside this class, should it be "private"?
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
go/pserver/cclient/test/main.c
Outdated
@@ -41,30 +43,31 @@ int main() { | |||
|
|||
unsigned char content[] = {0x00, 0x11, 0x22}; | |||
paddle_gradient grads[2] = { | |||
{"param_a", PADDLE_ELEMENT_TYPE_INT32, content, 3}, | |||
{"param_b", PADDLE_ELEMENT_TYPE_FLOAT32, content, 3}}; | |||
{"param_a", PADDLE_ELEMENT_TYPE_FLOAT32, content, 3}, |
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.
yes! I remember there is a bug here when I test the pserver program
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_paras = | ||
(paddle_parameter**)malloc(sizeof(paddle_parameter*) * parameterSize()); | ||
for (int i = 0; i < parameterSize(); ++i) { | ||
new_paras[i] = (paddle_parameter*)malloc(sizeof(paddle_parameter)); |
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.
没有找到对应的free。
另外,
//cclient.go
static inline void paddle_release_param(paddle_parameter* param)
释放parameter内存不应该由cclient负责吧? @helinwang ,既然由remoteUpdater申请内存,释放空间最好还是在同一个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.
对的,parameter内存不由cclient拥有。
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.
NewRemoteParameterUpdater destruct的时候需要释放对应成员变量的内存。
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.
目前parameterUpdater只分配了几个指针数组,而没有分配具体的content buffer,所以只负责free自己分配的几个指针成员
new_paras[i]->element_type = PADDLE_ELEMENT_TYPE_FLOAT32; | ||
new_paras[i]->name = (char*)para->getName().c_str(); | ||
new_paras[i]->content = | ||
(unsigned char*)(para->getBuf(type).get()->getData()); |
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 a suggestion, it's up to you, do we need to unify the variable abbrevtion? helin used to named parameter with param
, this part named with para. How do you think? Both is fine to me.
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
NewRemoteParameterUpdater(const OptimizationConfig& config, | ||
const std::string pserverSpec); | ||
~NewRemoteParameterUpdater() { | ||
if (newGradients_) { |
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 can't understand this condition, and we need to free the newGradient after release client, aren't we?
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
@jacquesqiao In future it's better to use the same PR, so reviewer can track the comment / reply. You can just force push to the PR branch if you rebased / did a merge. Please ask me if you are not sure how to do this :) |
|
||
namespace paddle { | ||
NewRemoteParameterUpdater::NewRemoteParameterUpdater( | ||
const OptimizationConfig &config, const std::string pserverSpec) |
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 to confirm, does OptimizationConfig
have all information about the optimizer used on each parameter? (parameters can have their own learning rate, L2 / L1 norm)
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, one OptimizationConfig is not enough, it needs more kinds optimizers when training a complicated network. e.g. some part use adagrad
optimizer, some part use Ftrl
optimizer https://arxiv.org/abs/1606.07792, which is I mentioned in last week. we can polish this part after we combining these modules together.
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, send the old parameter config to go cclient for now.
|
||
// create parameter server client. | ||
parameterClient_ = | ||
paddle_new_pserver_client((char *)pserverSpec_.c_str(), FLAGS_trainer_id); |
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 here should be paddle_new_pserver_client(..., FLAGS_trainer_id == 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.
done
LOG(INFO) << "paddle_begin_init_params done"; | ||
} else { | ||
paddle_get_params( | ||
parameterClient_, names_, newParameters_, (int)parameters_.size()); |
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.
It's more consistent / clear if use parameterSize()
rather than parameters_.size()
.
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
/// internal parameter client object for exchanging data with pserver | ||
client parameterClient_ = -1; | ||
/// the parameters for new pserver client | ||
paddle_parameter** newParameters_; |
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.
These three pointers need to be freed in the destructor.
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
|
||
for (int i = 0; i < parameterSize(); ++i) { | ||
ParameterPtr para = parameters_[i]; | ||
new_paras[i]->content_len = 10; |
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 having 10 here is not correct.
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_paras = | ||
(paddle_parameter**)malloc(sizeof(paddle_parameter*) * parameterSize()); | ||
for (int i = 0; i < parameterSize(); ++i) { | ||
new_paras[i] = (paddle_parameter*)malloc(sizeof(paddle_parameter)); |
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.
对的,parameter内存不由cclient拥有。
new_paras = | ||
(paddle_parameter**)malloc(sizeof(paddle_parameter*) * parameterSize()); | ||
for (int i = 0; i < parameterSize(); ++i) { | ||
new_paras[i] = (paddle_parameter*)malloc(sizeof(paddle_parameter)); |
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.
NewRemoteParameterUpdater destruct的时候需要释放对应成员变量的内存。
/** | ||
* initialize the internal parameter client and itself. | ||
*/ | ||
virtual void init(const std::vector<ParameterPtr>& parameters); |
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.
we will change the style to google c++ style, it is the most popular style in c++ opensource world, why not?
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.
emm... Do we need to unify the Go style and c++ style in naming function? It seems that Go style function naming convention is better. How do you think?
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 need to following Google C++ style for C++ files.
Btw, for C file we have a different style used here: https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/capi/main.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.
The function interface like init
, startBatch
of NewRemoteParameterUpdater is inherited from parent class ParameterUpdater
that use lowercase as the first letter. So this function name has to maintain the style now, but I also agree that we use Google C++ style for C++ in the future.
* @param new_paras | ||
* @param type | ||
*/ | ||
void initNewParameter(paddle_parameter**& new_paras, ParameterType type) { |
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.
initNewParameter
seems only called inside this class, should it be "private"?
for (int i = 0; i < parameterSize(); ++i) { | ||
ParameterPtr para = parameters_[i]; | ||
new_paras[i]->content_len = 10; | ||
new_paras[i]->element_type = PADDLE_ELEMENT_TYPE_FLOAT32; |
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.
Need a comment that type is defined in "Vector.h" with typedef VectorT<real> Vector;
, so parameter element type is always real
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
go/pserver/cclient/test/main.c
Outdated
fail(); | ||
} | ||
|
||
paddle_parameter* params[2] = {NULL, NULL}; | ||
char* names[] = {"param_a", "param_b"}; | ||
if (!paddle_get_params(c, names, params, 2)) { |
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.
Sorry about this mistake from me!
go/pserver/cclient/cclient.go
Outdated
var gs []pserver.Gradient | ||
for i := 0; i < int(total); i++ { | ||
grad := (*C.paddle_gradient)(unsafe.Pointer((uintptr(unsafe.Pointer(grads)) + uintptr(i)*unsafe.Sizeof(*grads)))) | ||
grad := *(**C.paddle_gradient)(unsafe.Pointer((uintptr(unsafe.Pointer(grads)) + uintptr(i)*unsafe.Sizeof(*grads)))) |
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.
Really sorry about this mistake from me. Must take you very long to debug!
go/pserver/cclient/cclient.go
Outdated
@@ -204,12 +204,14 @@ func paddle_get_params(client C.client, names **C.char, dst **C.paddle_parameter | |||
} | |||
|
|||
p := ps[i] | |||
param := *(**C.paddle_parameter)(unsafe.Pointer((uintptr(unsafe.Pointer(dst)) + uintptr(i)*unsafe.Sizeof(*dst)))) | |||
paramPtr := (**C.paddle_parameter)(unsafe.Pointer((uintptr(unsafe.Pointer(dst)) + uintptr(i)*unsafe.Sizeof(*dst)))) |
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.
Good catch! I got used to Go treating ->
as .
(inferred according to type automatically on whether dereference or not). Now I realized cgo should be treated more like C than Go :)
go/pserver/cclient/test/main.c
Outdated
fail(); | ||
} | ||
|
||
printf("test success!\n"); |
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.
Let's follow the Unix way, do not print anything (with return code 0) when everything went well.
If we print success on every test, the output would be very messy.
fail(); | ||
} | ||
|
||
printf("test success!\n"); |
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.
Let's follow the Unix way, do not print anything (with return code 0) when everything went well.
If we print success on every test, the output would be very messy.
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, removed
go/pserver/optimizer.c
Outdated
@@ -32,7 +32,14 @@ int update_SGD(void* optimizer, | |||
const void* gradient, | |||
int num_bytes) { | |||
SGD_optimizer* o = (SGD_optimizer*)optimizer; | |||
// TODO | |||
// TODO(a simple SGD implement) |
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 simple SGD implementation is already done, maybe remove this 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, removed
go/pserver/service.go
Outdated
@@ -29,6 +29,10 @@ type Parameter struct { | |||
Content []byte | |||
} | |||
|
|||
func (p *Parameter) toString() { |
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 this function necessary (not used anywhere).
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,removed
/** | ||
* initialize the internal parameter client and itself. | ||
*/ | ||
virtual void init(const std::vector<ParameterPtr>& parameters); |
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 need to following Google C++ style for C++ files.
Btw, for C file we have a different style used here: https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/capi/main.h
|
||
for (int i = 0; i < parameterSize(); ++i) { | ||
ParameterPtr param = parameters_[i]; | ||
new_params[i]->content_len = 10; |
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.
Maybe remove this line? (line 92 does the same thing correctly)
void NewRemoteParameterUpdater::init( | ||
const std::vector<ParameterPtr> ¶meters) { | ||
ParameterUpdater::init(parameters); | ||
LOG(INFO) << "NewRemoteParameterUpdater init 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.
What does "in" in "NewRemoteParameterUpdater init in" mean?
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++!
Need to resolve conflicts before merging! |
refs:
issue: #2274
old pr: #2330
测试方法:
1,编译。
2,编译完成之后运行 go run ./go/cmd/pserver/pserver.go -port 3000 会在本地启动一个parameter server,监听3000端口。
3,python paddle/go/pserver/cclient/test/test_train.py
增加了一个简单的梯度下降optimizer,已经可以正常训练和收敛了