Skip to content

Commit

Permalink
Add SGD Kernel Go Package (#1637)
Browse files Browse the repository at this point in the history
* add sgd kernel using eigen

* test style

* move kernel to go dir

* add kernel test

* refine test

* fix eigen3 header file

* trigger go unittest

* fix ci

* fix ci

* fix ci

* follow comments

* trigger go test

* update

* follow comments

* update

* update

* fix code style

* fix dockerfile
  • Loading branch information
QiJune committed Jan 17, 2020
1 parent 4fbc73a commit 36e99d0
Show file tree
Hide file tree
Showing 13 changed files with 147 additions and 6 deletions.
18 changes: 18 additions & 0 deletions .clang-format
@@ -0,0 +1,18 @@
---
Language: Cpp
BasedOnStyle: Google
IndentWidth: 2
TabWidth: 2
ContinuationIndentWidth: 4
AccessModifierOffset: -1 # The private/protected/public has no indent in class
Standard: Cpp11
AllowAllParametersOfDeclarationOnNextLine: true
BinPackParameters: false
BinPackArguments: false
---
Language: Proto
BasedOnStyle: Google
IndentWidth: 2
TabWidth: 2
ContinuationIndentWidth: 4
---
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -14,6 +14,8 @@ __pycache__/


# C extensions # C extensions
*.so *.so
*.o
*.a


# Distribution / packaging # Distribution / packaging
.Python .Python
Expand Down
19 changes: 17 additions & 2 deletions .pre-commit-config.yaml
Expand Up @@ -21,11 +21,26 @@ repos:
hooks: hooks:
- id: mypy - id: mypy
args: [--ignore-missing-imports, --follow-imports=skip] args: [--ignore-missing-imports, --follow-imports=skip]
- repo: local
hooks:
- id: clang-format
name: clang-format
description: Format files with ClangFormat.
entry: bash ./scripts/codestyle/clang_format.hook -i
language: system
files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto)$
- repo: local
hooks:
- id: cpplint-cpp-source
name: cpplint
description: Check C++ code style using cpplint.py.
entry: bash ./scripts/codestyle/cpplint_precommit.hook
language: system
files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx)$
- repo: git://github.com/dnephin/pre-commit-golang - repo: git://github.com/dnephin/pre-commit-golang
rev: v0.3.3 rev: v0.3.3
hooks: hooks:
- id: go-fmt - id: go-fmt
- id: go-lint - id: go-lint
- id: validate-toml - id: validate-toml
- id: no-go-testing - id: no-go-testing

1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -8,6 +8,7 @@ addons:
- docker-ce - docker-ce
- python3-pip - python3-pip
- python3-setuptools - python3-setuptools
- clang-format


install: install:
- docker version - docker version
Expand Down
11 changes: 10 additions & 1 deletion elasticdl/Makefile
Expand Up @@ -5,11 +5,20 @@ EDL_PROTO_FILE = elasticdl/proto/elasticdl.proto
GO_FILE_DIR = elasticdl/pkg/proto GO_FILE_DIR = elasticdl/pkg/proto
GO_PB_FILE = $(GO_FILE_DIR)/elasticdl.pb.go GO_PB_FILE = $(GO_FILE_DIR)/elasticdl.pb.go


all: python_pb $(GO_PB_FILE) CXX = g++
CAPI_DIR = elasticdl/pkg/kernel/capi

all: python_pb $(GO_PB_FILE) kernel


python_pb: python_pb:
$(PYTHON) -m grpc_tools.protoc -I . $(EDL_PROTO_FILE) --python_out=. --grpc_python_out=. $(PYTHON) -m grpc_tools.protoc -I . $(EDL_PROTO_FILE) --python_out=. --grpc_python_out=.


$(GO_PB_FILE): $(EDL_PROTO_FILE) $(GO_PB_FILE): $(EDL_PROTO_FILE)
mkdir -p $(GO_FILE_DIR) mkdir -p $(GO_FILE_DIR)
protoc -I . $< --go_out=plugins=grpc:. protoc -I . $< --go_out=plugins=grpc:.

kernel:
${CXX} -O3 -std=c++11 ${CAPI_DIR}/kernel_api.cc -c -o ${CAPI_DIR}/libkernel_api.o
ar crv ${CAPI_DIR}/libkernel_api.a ${CAPI_DIR}/libkernel_api.o
clean:
rm -rf ${CAPI_DIR}/*.o ${CAPI_DIR}/*.a
4 changes: 2 additions & 2 deletions elasticdl/docker/Dockerfile
Expand Up @@ -6,7 +6,7 @@ FROM ${BASE_IMAGE}
COPY elasticdl/docker/bashrc /etc/bash.bashrc COPY elasticdl/docker/bashrc /etc/bash.bashrc
RUN chmod a+rwx /etc/bash.bashrc RUN chmod a+rwx /etc/bash.bashrc


RUN apt-get update && apt-get install -y unzip curl git software-properties-common RUN apt-get update && apt-get install -y unzip curl git software-properties-common libeigen3-dev


COPY elasticdl/requirements.txt /requirements.txt COPY elasticdl/requirements.txt /requirements.txt
ARG EXTRA_PYPI_INDEX=https://pypi.org/simple ARG EXTRA_PYPI_INDEX=https://pypi.org/simple
Expand All @@ -15,4 +15,4 @@ RUN pip install -r /requirements.txt --extra-index-url=${EXTRA_PYPI_INDEX}
WORKDIR / WORKDIR /
ENV PYTHONPATH=/ ENV PYTHONPATH=/
COPY elasticdl /elasticdl COPY elasticdl /elasticdl
RUN make -f elasticdl/Makefile RUN make -f elasticdl/Makefile python_pb
4 changes: 3 additions & 1 deletion elasticdl/docker/Dockerfile.dev
Expand Up @@ -6,7 +6,9 @@ FROM ${BASE_IMAGE}
COPY elasticdl/docker/bashrc /etc/bash.bashrc COPY elasticdl/docker/bashrc /etc/bash.bashrc
RUN chmod a+rwx /etc/bash.bashrc RUN chmod a+rwx /etc/bash.bashrc


RUN apt-get update && apt-get install -y unzip curl git software-properties-common wget RUN apt update && \
apt install -y unzip curl git software-properties-common g++ wget \
libeigen3-dev


COPY elasticdl/requirements.txt /requirements.txt COPY elasticdl/requirements.txt /requirements.txt
COPY elasticdl/requirements-dev.txt /requirements-dev.txt COPY elasticdl/requirements-dev.txt /requirements-dev.txt
Expand Down
13 changes: 13 additions & 0 deletions elasticdl/pkg/kernel/capi/kernel_api.cc
@@ -0,0 +1,13 @@
#include "kernel_api.h"

#include <eigen3/Eigen/Dense>

void SGD(float* grad, float* param, double lr, long long size) {
Eigen::Map<Eigen::Array<float, 1, Eigen::Dynamic>> eg{
grad, static_cast<Eigen::Index>(size)};

Eigen::Map<Eigen::Array<float, 1, Eigen::Dynamic>> ep{
param, static_cast<Eigen::Index>(size)};

ep -= lr * eg;
}
13 changes: 13 additions & 0 deletions elasticdl/pkg/kernel/capi/kernel_api.h
@@ -0,0 +1,13 @@
#ifndef ELASTICDL_PKG_KERNEL_CAPI_KERNEL_API_H_
#define ELASTICDL_PKG_KERNEL_CAPI_KERNEL_API_H_

#ifdef __cplusplus
extern "C" {
#endif

void SGD(float* grad, float* param, double lr, long long size);

#ifdef __cplusplus
}
#endif
#endif
13 changes: 13 additions & 0 deletions elasticdl/pkg/kernel/kernel.go
@@ -0,0 +1,13 @@
package kernel

// #cgo LDFLAGS: -L./capi -lkernel_api
// #include "capi/kernel_api.h"
import "C"
import "unsafe"

// SGD kernel
func SGD(grad []float32, param []float32, lr float64, size int64) {
gradPtr := (*C.float)(unsafe.Pointer(&grad[0]))
paramPtr := (*C.float)(unsafe.Pointer(&param[0]))
C.SGD(gradPtr, paramPtr, C.double(lr), C.longlong(size))
}
27 changes: 27 additions & 0 deletions elasticdl/pkg/kernel/kernel_test.go
@@ -0,0 +1,27 @@
package kernel

import "testing"
import "math/rand"
import "github.com/stretchr/testify/assert"

func TestSGD(t *testing.T) {
const size int = 10
a := make([]float32, size)
b := make([]float32, size)
var lr float32 = 0.1

for i := 0; i < size; i++ {
a[i] = rand.Float32()
b[i] = rand.Float32()
}

expected := make([]float32, size)

for i := 0; i < size; i++ {
expected[i] = b[i] - lr*a[i]
}

SGD(a, b, float64(lr), int64(size))

assert.Equal(t, b, expected)
}
1 change: 1 addition & 0 deletions scripts/codestyle/clang_format.hook
@@ -0,0 +1 @@
clang-format $@
27 changes: 27 additions & 0 deletions scripts/codestyle/cpplint_precommit.hook
@@ -0,0 +1,27 @@
#!/bin/bash

TOTAL_ERRORS=0
if [[ ! $TRAVIS_BRANCH ]]; then
# install cpplint on local machine.
if [[ ! $(which cpplint) ]]; then
pip install cpplint
fi
# diff files on local machine.
files=$(git diff --cached --name-status | awk 'Extra open brace or missing close brace2}')
else
# diff files between PR and latest commit on Travis CI.
branch_ref=$(git rev-parse "$TRAVIS_BRANCH")
head_ref=$(git rev-parse HEAD)
files=$(git diff --name-status $branch_ref $head_ref | awk 'Extra open brace or missing close brace2}')
fi
# The trick to remove deleted files: https://stackoverflow.com/a/2413151
for file in $files; do
if [[ $file =~ ^(patches/.*) ]]; then
continue;
else
cpplint --filter=-readability/fn_size $file;
TOTAL_ERRORS=$(expr $TOTAL_ERRORS + $?);
fi
done

exit $TOTAL_ERRORS

0 comments on commit 36e99d0

Please sign in to comment.