client.go 4.9 KB
Newer Older
1
// Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
D
dongzhihong 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14

// 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.

H
Helin Wang 已提交
15 16 17
package main

/*
18 19 20 21 22
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define PADDLE_MASTER_OK    0
#define PADDLE_MASTER_ERROR -1
H
Helin Wang 已提交
23

H
Helin Wang 已提交
24 25 26
#define PADDLE_SAVE_MODEL_OK   1
#define PADDLE_SAVE_MODEL_SKIP 0

H
Helin Wang 已提交
27 28 29 30 31
typedef int paddle_master_client;
*/
import "C"

import (
32
	"strings"
H
Helin Wang 已提交
33
	"sync"
34
	"time"
H
Helin Wang 已提交
35 36 37
	"unsafe"

	"github.com/PaddlePaddle/Paddle/go/master"
38
	log "github.com/inconshreveable/log15"
H
Helin Wang 已提交
39 40 41 42 43 44
)

var mu sync.Mutex
var handleMap = make(map[C.paddle_master_client]*master.Client)
var curHandle C.paddle_master_client

45 46 47 48 49 50
func init() {
	log.Root().SetHandler(
		log.LvlFilterHandler(log.LvlWarn, log.CallerStackHandler("%+v", log.StderrHandler)),
	)
}

H
Helin Wang 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
func add(c *master.Client) C.paddle_master_client {
	mu.Lock()
	defer mu.Unlock()
	client := curHandle
	curHandle++
	handleMap[client] = c
	return client
}

func get(client C.paddle_master_client) *master.Client {
	mu.Lock()
	defer mu.Unlock()
	return handleMap[client]
}

func remove(client C.paddle_master_client) *master.Client {
	mu.Lock()
	defer mu.Unlock()
	h := handleMap[client]
	delete(handleMap, client)
	return h
}

74
//export paddle_new_etcd_master_client
75 76
//
// bufSize is the record buffer size.
77 78
func paddle_new_etcd_master_client(etcdEndpoints *C.char, timeout int, bufSize int) C.paddle_master_client {
	p := C.GoString(etcdEndpoints)
79 80 81 82 83
	endpoints := strings.Split(p, ",")
	c, err := master.NewClient(
		master.WithEtcd(endpoints, time.Duration(timeout)*time.Second),
		master.WithBuffer(bufSize),
	)
84 85 86
	if err != nil {
		panic(err)
	}
87

88
	return add(c)
H
Helin Wang 已提交
89 90
}

91
//export paddle_new_master_client
92 93
//
// bufSize is the record buffer size.
94
func paddle_new_master_client(addr *C.char, bufSize int) C.paddle_master_client {
H
Helin Wang 已提交
95
	a := C.GoString(addr)
96 97 98 99 100
	c, err := master.NewClient(master.WithAddr(a), master.WithBuffer(bufSize))
	if err != nil {
		panic(err)
	}

H
Helin Wang 已提交
101 102 103
	return add(c)
}

104 105 106
//export paddle_release_master_client
func paddle_release_master_client(client C.paddle_master_client) {
	remove(client)
H
Helin Wang 已提交
107 108
}

109 110 111 112 113 114
//export paddle_start_get_records
func paddle_start_get_records(client C.paddle_master_client, pass C.int) {
	c := get(client)
	c.StartGetRecords(int(pass))
}

H
Helin Wang 已提交
115 116 117 118 119
//export paddle_set_dataset
func paddle_set_dataset(client C.paddle_master_client, path **C.char, size C.int) C.int {
	c := get(client)
	var paths []string
	for i := 0; i < int(size); i++ {
120
		ptr := (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(path)) + uintptr(i)*unsafe.Sizeof(*path)))
H
Helin Wang 已提交
121 122 123 124 125
		str := C.GoString(*ptr)
		paths = append(paths, str)
	}
	err := c.SetDataset(paths)
	if err != nil {
G
gongweibao 已提交
126 127
		log.Error("error set dataset",
			log.Ctx{"error": err, "paths": paths})
128 129 130 131 132 133
		return C.PADDLE_MASTER_ERROR
	}

	return C.PADDLE_MASTER_OK
}

134 135
// paddle_next_record gets the nexts training record.
//
136
// returns number of bytes of the records if success, -1 if failed, -2 if pass end.
137
//
138 139 140
//export paddle_next_record
func paddle_next_record(client C.paddle_master_client, record **C.uchar) C.int {
	c := get(client)
G
gongweibao 已提交
141 142
	r, err := c.NextRecord()
	if err != nil {
143 144 145 146 147 148
		// NOTE: use errors to indicate pass ends
		if err.Error() == master.ErrAllTaskFailed.Error() ||
			err.Error() == master.ErrNoMoreAvailable.Error() ||
			err.Error() == master.ErrPassBefore.Error() {
			return -2
		}
149
		*record = (*C.uchar)(nil)
G
gongweibao 已提交
150
		return -1
G
gongweibao 已提交
151 152
	}

153
	if len(r) == 0 {
G
gongweibao 已提交
154
		// Empty record
155
		*record = (*C.uchar)(nil)
156
		return 0
H
Helin Wang 已提交
157 158
	}

159 160 161 162 163 164
	size := C.size_t(len(r))
	*record = (*C.uchar)(C.malloc(size))
	C.memcpy(unsafe.Pointer(*record), unsafe.Pointer(&r[0]), size)
	return C.int(size)
}

165 166 167
// paddle_request_save_model requests the master server to approve the
// caller to save the model.
//
H
Helin Wang 已提交
168
// returns 1 if the save the model request is approved, 0 if the
169 170 171 172 173 174 175 176
// request is rejected because other trainer is saving the model, -1
// if error happened.
//
//export paddle_request_save_model
func paddle_request_save_model(client C.paddle_master_client, trainerID string, blockMS int) C.int {
	c := get(client)
	need, err := c.RequestSaveModel(trainerID, time.Duration(blockMS)*time.Millisecond)
	if err != nil {
177
		log.Error("error request save model", log.Ctx{"error": err})
H
Helin Wang 已提交
178
		return C.PADDLE_MASTER_ERROR
179 180 181
	}

	if need {
H
Helin Wang 已提交
182
		return C.PADDLE_SAVE_MODEL_OK
183 184
	}

H
Helin Wang 已提交
185
	return C.PADDLE_SAVE_MODEL_SKIP
186 187
}

188 189 190 191 192 193
//export mem_free
func mem_free(p unsafe.Pointer) {
	// "free" may be a better name for this function, but doing so
	// will cause calling any function of this library from Python
	// ctypes hanging.
	C.free(p)
H
Helin Wang 已提交
194 195 196
}

func main() {}