Skip to content
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

Merged
merged 13 commits into from
Jun 14, 2017
Merged
Prev Previous commit
Next Next commit
add simple updater, this version can train a model
  • Loading branch information
jacquesqiao committed Jun 10, 2017

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit c44f5dd883b49d063d336dda874f1794270c2982
1 change: 0 additions & 1 deletion go/pserver/cclient/cclient.go
Original file line number Diff line number Diff line change
@@ -42,7 +42,6 @@ import (
"strings"
"sync"
"unsafe"
"fmt"

"github.com/PaddlePaddle/Paddle/go/pserver"
)
4 changes: 4 additions & 0 deletions go/pserver/cclient/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.0)

add_executable(main main.c)
add_dependencies(main paddle_pserver_cclient)
add_executable(test_cclient test_cclient.c)
add_dependencies(test_cclient paddle_pserver_cclient)

if(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "-framework CoreFoundation -framework Security")
@@ -10,7 +12,9 @@ endif()
if(PROJ_ROOT)
include_directories(${CMAKE_BINARY_DIR}/go/pserver/cclient/)
target_link_libraries(main ${CMAKE_BINARY_DIR}/go/pserver/cclient/libpaddle_pserver_cclient.a pthread)
target_link_libraries(test_cclient ${CMAKE_BINARY_DIR}/go/pserver/cclient/libpaddle_pserver_cclient.a pthread)
else(PROJ_ROOT)
include_directories(${CMAKE_BINARY_DIR})
target_link_libraries(main ${CMAKE_BINARY_DIR}/libpaddle_pserver_cclient.a pthread)
target_link_libraries(test_cclient ${CMAKE_BINARY_DIR}/libpaddle_pserver_cclient.a pthread)
endif(PROJ_ROOT)
71 changes: 20 additions & 51 deletions go/pserver/cclient/test/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <stdio.h>
#include <stdlib.h>

#include "libpaddle_pserver_cclient.h"

@@ -10,21 +9,6 @@ void fail() {
exit(-1);
}

void print_parameter(paddle_gradient* param) {
if (param == NULL) {
printf("param is NULL!!\n");
} else {
printf("==== parameter ====\n");
printf("name: %s\n", param->name);
printf("content_len: %d\n", param->content_len);
printf("content_type: %d\n", param->element_type);
for (int i = 0; i < param->content_len; ++i) {
printf("0x%x ", param->content[i]);
}
printf("\n\n");
}
}

int main() {
char addr[] = "localhost:3000";
client c = paddle_new_pserver_client(addr, 1);
@@ -33,51 +17,44 @@ int main() {
paddle_parameter param;
char name_a[] = "param_a";
char name_b[] = "param_b";
unsigned char content1[] = {0x01, 0x02, 0x03};
unsigned char content[] = {0x00, 0x11, 0x22};
param.element_type = PADDLE_ELEMENT_TYPE_FLOAT32;
param.name = name_a;
param.content = content1;
param.content = content;
param.content_len = 3;
if (paddle_init_param(c, param, NULL, 0) != 0) {
goto retry;
}
unsigned char content2[] = {0x04, 0x05, 0x06};
param.element_type = PADDLE_ELEMENT_TYPE_INT32;
param.name = name_b;
param.content = content2;
param.content = content;
param.content_len = 3;
if (paddle_init_param(c, param, NULL, 0) != 0) {
goto retry;
}

if (paddle_finish_init_params(c) != 0) {
goto retry;
}
} else {
fail();
}

unsigned char content1[] = {0x12, 0x23, 0x34};
unsigned char content2[] = {0x45, 0x56, 0x67};

paddle_gradient** new_params =
(paddle_gradient**)malloc(sizeof(paddle_gradient*) * 2);
new_params[0] = (paddle_gradient*)malloc(sizeof(paddle_gradient));
new_params[0]->name = "param_a";
new_params[0]->content = content1;
new_params[0]->content_len = 3;
new_params[0]->element_type = PADDLE_ELEMENT_TYPE_FLOAT32;

new_params[1] = (paddle_gradient*)malloc(sizeof(paddle_gradient));
new_params[1]->name = "param_b";
new_params[1]->content = content2;
new_params[1]->content_len = 3;
new_params[1]->element_type = PADDLE_ELEMENT_TYPE_INT32;

print_parameter(new_params[0]);
print_parameter(new_params[1]);

if (paddle_send_grads(c, new_params, 2) != 0) {
unsigned char content[] = {0x00, 0x11, 0x22};
paddle_gradient** grads =
(paddle_gradient**)malloc(sizeof(paddle_gradient*) * 2);
grads[0] = (paddle_gradient*)malloc(sizeof(paddle_gradient));
grads[0]->name = "param_a";
grads[0]->content = content;
grads[0]->content_len = 3;
grads[0]->element_type = PADDLE_ELEMENT_TYPE_FLOAT32;

grads[1] = (paddle_gradient*)malloc(sizeof(paddle_gradient));
grads[1]->name = "param_b";
grads[1]->content = content;
grads[1]->content_len = 3;
grads[1]->element_type = PADDLE_ELEMENT_TYPE_INT32;

if (paddle_send_grads(c, grads, 2) != 0) {
fail();
}

@@ -87,15 +64,6 @@ int main() {
fail();
}

print_parameter(params[0]);
print_parameter(params[1]);

/// change name of parameter.
char* names2[] = {"param_1", "param_2"};
if (paddle_get_params(c, names2, params, 2) == 0) {
fail();
}

// get parameters again by reusing the allocated parameter buffers.
if (paddle_get_params(c, names, params, 2) != 0) {
fail();
@@ -109,5 +77,6 @@ int main() {
}

printf("test success!\n");
Copy link
Contributor

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.


return 0;
}
114 changes: 114 additions & 0 deletions go/pserver/cclient/test/test_cclient.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include <stdio.h>
#include <stdlib.h>

#include "libpaddle_pserver_cclient.h"

typedef float real;

void fail() {
// TODO(helin): fix: gtest using cmake is not working, using this
// hacky way for now.
printf("test failed.\n");
exit(-1);
}

void print_parameter(paddle_gradient* param) {
if (param == NULL) {
printf("param is NULL!!\n");
} else {
printf("==== parameter ====\n");
printf("name: %s\n", param->name);
printf("content_len: %d\n", param->content_len);
printf("content_type: %d\n", param->element_type);
for (int i = 0; i < param->content_len/sizeof(real); ++i) {
printf("%f ", ((float *)param->content)[i]);
}
printf("\n\n");
}
}

int main() {
char addr[] = "localhost:3000";
client c = paddle_new_pserver_client(addr, 1);

char* names[] = {"param_a", "param_b"};
retry:

if (paddle_begin_init_params(c)) {
paddle_parameter param;
real param_content1[] = {0.1, 0.2, 0.3};
param.element_type = PADDLE_ELEMENT_TYPE_FLOAT32;
param.name = names[0];
param.content = (unsigned char*)param_content1;
param.content_len = 3 * sizeof(real);
if (paddle_init_param(c, param, NULL, 0) != 0) {
goto retry;
}
real param_content2[] = {0.4, 0.5, 0.6};
param.element_type = PADDLE_ELEMENT_TYPE_INT32;
param.name = names[1];
param.content = (unsigned char*)param_content2;
param.content_len = 3 * sizeof(real);
if (paddle_init_param(c, param, NULL, 0) != 0) {
goto retry;
}

if (paddle_finish_init_params(c) != 0) {
goto retry;
}
} else {
fail();
}

printf("get initialized parameters from pserver:\n");
paddle_parameter* param_ptrs[2] = {NULL, NULL};
if (paddle_get_params(c, names, param_ptrs, 2) != 0) {
fail();
}
print_parameter(param_ptrs[0]);
print_parameter(param_ptrs[1]);

printf("send gradient to pserver:\n");
real gradient_content1[] = {0.01, 0.02, 0.03};
real gradinet_content2[] = {0.04, 0.05, 0.06};

paddle_gradient** grads =
(paddle_gradient**)malloc(sizeof(paddle_gradient*) * 2);
grads[0] = (paddle_gradient*)malloc(sizeof(paddle_gradient));
grads[0]->name = names[0];
grads[0]->content = (unsigned char*)gradient_content1;
grads[0]->content_len = 3 * sizeof(real);
grads[0]->element_type = PADDLE_ELEMENT_TYPE_FLOAT32;

grads[1] = (paddle_gradient*)malloc(sizeof(paddle_gradient));
grads[1]->name = names[1];
grads[1]->content = (unsigned char*)gradinet_content2;
grads[1]->content_len = 3 * sizeof(real);
grads[1]->element_type = PADDLE_ELEMENT_TYPE_INT32;

print_parameter(grads[0]);
print_parameter(grads[1]);

if (paddle_send_grads(c, grads, 2) != 0) {
fail();
}

printf("get updated parameters from pserver:\n");
// get parameters again by reusing the allocated parameter buffers.
if (paddle_get_params(c, names, param_ptrs, 2) != 0) {
fail();
}

print_parameter(param_ptrs[0]);
print_parameter(param_ptrs[1]);

paddle_release_param(param_ptrs[0]);
paddle_release_param(param_ptrs[1]);

if (paddle_save_model(c, "/tmp/") != 0) {
fail();
}

printf("test success!\n");
Copy link
Contributor

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, removed

return 0;
}
8 changes: 7 additions & 1 deletion go/pserver/optimizer.c
Original file line number Diff line number Diff line change
@@ -32,7 +32,13 @@ int update_SGD(void* optimizer,
const void* gradient,
int num_bytes) {
SGD_optimizer* o = (SGD_optimizer*)optimizer;
// TODO
// TODO(a simple SGD implement)
Copy link
Contributor

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, removed

float* parameter = (float *)buffer;
float* grad = (float *)gradient;

for(int i = 0; i < num_bytes/sizeof(float); ++i) {
parameter[i] -= o->learning_rate * grad[i];
}
return 0;
}

2 changes: 0 additions & 2 deletions paddle/trainer/NewRemoteParameterUpdater.cpp
Original file line number Diff line number Diff line change
@@ -73,8 +73,6 @@ void NewRemoteParameterUpdater::init(
void NewRemoteParameterUpdater::updateImpl(Parameter *para) {}

void NewRemoteParameterUpdater::finishBatch(real cost) {
LOG(INFO) << "finishBatch in, cost: " << cost;

// send gradient to parameter server.
paddle_send_grads(parameterClient_, newGradients_, parameterSize());
// get the updated parameter from parameterClient.
2 changes: 1 addition & 1 deletion paddle/trainer/NewRemoteParameterUpdater.h
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ class NewRemoteParameterUpdater : public ParameterUpdater {
new_params[i]->name = (char*)param->getName().c_str();
new_params[i]->content =
(unsigned char*)(param->getBuf(type).get()->getData());
new_params[i]->content_len = (int)param->getBuf(type).get()->getSize();
new_params[i]->content_len = (int)param->getBuf(type).get()->getSize() * sizeof(real);
}
return new_params;
}