linux pip install supporting & code reconstructing

This commit is contained in:
Young 2016-06-02 15:45:26 +08:00
Родитель e5bd34c91f
Коммит 185b871072
8 изменённых файлов: 180 добавлений и 114 удалений

Просмотреть файл

@ -1,4 +0,0 @@
.PHONY: test
test:
cd ./multiverso && python -m unittest test.TestMultiversoTables.test_array
cd ./multiverso && python -m unittest test.TestMultiversoTables.test_matrix

Просмотреть файл

@ -1,10 +1,12 @@
# Requirements
I presume you followed the [README](../../README.md) and have build multiverso successfully.
# Run tests
```
make test
nosetests
```

Просмотреть файл

@ -1,5 +1,5 @@
#!/usr/bin/env python
# coding:utf8
from api import init, shutdown, barrier, workers_num, worker_id, server_id,\
ArrayTableHandler, MatrixTableHandler
from api import init, shutdown, barrier, workers_num, worker_id, server_id
from tables import ArrayTableHandler, MatrixTableHandler

Просмотреть файл

@ -1,7 +1,7 @@
#!/usr/bin/env python
# coding:utf8
from ctypes import *
import ctypes
from utils import Loader
import numpy as np
@ -11,8 +11,8 @@ mv_lib = Loader.get_lib()
def init(args=[]):
n = len(args)
args_type = c_char_p * n
mv_lib.MV_Init(pointer(c_int(n)), args_type(*[c_char_p(arg) for arg in args]))
args_type = ctypes.c_char_p * n
mv_lib.MV_Init(ctypes.pointer(ctypes.c_int(n)), args_type(*[ctypes.c_char_p(arg) for arg in args]))
def shutdown():
@ -32,95 +32,4 @@ def worker_id():
def server_id():
return my_lib.MV_ServerId()
class TableHandler(object):
def __init__(self, size):
raise NotImplementedError("You must implement the __init__ method.")
def get(self, size):
raise NotImplementedError("You must implement the get method.")
def add(self, data):
raise NotImplementedError("You must implement the add method.")
# types
C_FLOAT_P = POINTER(c_float)
class ArrayTableHandler(TableHandler):
def __init__(self, size):
self._handler = c_void_p()
self._size = size
mv_lib.MV_NewArrayTable(size, byref(self._handler))
def get(self):
'''
Data type of return value is numpy.ndarray
'''
data = np.zeros((self._size, ), dtype=np.dtype("float32"))
mv_lib.MV_GetArrayTable(self._handler, data.ctypes.data_as(C_FLOAT_P), self._size)
return data
def add(self, data):
'''
Data type of `data` is numpy.ndarray
'''
if not isinstance(data, np.ndarray):
data = np.array(data)
assert(data.size == self._size)
data = data.astype(np.float32)
mv_lib.MV_AddArrayTable(self._handler, data.ctypes.data_as(C_FLOAT_P), self._size)
class MatrixTableHandler(TableHandler):
def __init__(self, num_row, num_col):
self._handler = c_void_p()
self._num_row = num_row
self._num_col = num_col
self._size = num_col * num_row
mv_lib.MV_NewMatrixTable(num_row, num_col, byref(self._handler))
def get(self, row_ids=None):
'''
If row_ids is None, we will return all rows as numpy.narray , e.g.
array([[1, 3], [3, 4]]). Otherwise we will return the data according
to the row_ids
'''
if row_ids is None:
data = np.zeros((self._num_row, self._num_col), dtype=np.dtype("float32"))
mv_lib.MV_GetMatrixTableAll(self._handler, data.ctypes.data_as(C_FLOAT_P), self._size)
return data
else:
row_ids_n = len(row_ids)
int_array_type = c_int * row_ids_n
data = np.zeros((row_ids_n, self._num_col), dtype=np.dtype("float32"))
mv_lib.MV_GetMatrixTableByRows(self._handler, data.ctypes.data_as(C_FLOAT_P),
row_ids_n * self._num_col,
int_array_type(*row_ids), row_ids_n)
return data
def add(self, data=None, row_ids=None):
'''
If row_ids is None, we will add all data, and the data
should be a list, e.g. [1, 2, 3, ...]
Otherwise we will add the data according to the row_ids
'''
assert(data is not None)
if not isinstance(data, np.ndarray):
data = np.array(data)
data = data.astype(np.float32)
if row_ids is None:
assert(data.size == self._size)
mv_lib.MV_AddMatrixTableAll(self._handler, data.ctypes.data_as(C_FLOAT_P), self._size)
else:
row_ids_n = len(row_ids)
assert(data.size == row_ids_n * self._num_col)
int_array_type = c_int * row_ids_n
mv_lib.MV_AddMatrixTableByRows(self._handler, data.ctypes.data_as(C_FLOAT_P),
row_ids_n * self._num_col,
int_array_type(*row_ids), row_ids_n)
return mv_lib.MV_ServerId()

Просмотреть файл

@ -0,0 +1,100 @@
#!/usr/bin/env python
# coding:utf8
import ctypes
from utils import Loader
import numpy as np
mv_lib = Loader.get_lib()
class TableHandler(object):
def __init__(self, size):
raise NotImplementedError("You must implement the __init__ method.")
def get(self, size):
raise NotImplementedError("You must implement the get method.")
def add(self, data):
raise NotImplementedError("You must implement the add method.")
# types
C_FLOAT_P = ctypes.POINTER(ctypes.c_float)
class ArrayTableHandler(TableHandler):
def __init__(self, size):
self._handler = ctypes.c_void_p()
self._size = size
mv_lib.MV_NewArrayTable(size, ctypes.byref(self._handler))
def get(self):
'''
Data type of return value is numpy.ndarray
'''
data = np.zeros((self._size, ), dtype=np.dtype("float32"))
mv_lib.MV_GetArrayTable(self._handler, data.ctypes.data_as(C_FLOAT_P), self._size)
return data
def add(self, data):
'''
Data type of `data` is numpy.ndarray
'''
if not isinstance(data, np.ndarray):
data = np.array(data)
assert(data.size == self._size)
data = data.astype(np.float32)
mv_lib.MV_AddArrayTable(self._handler, data.ctypes.data_as(C_FLOAT_P), self._size)
class MatrixTableHandler(TableHandler):
def __init__(self, num_row, num_col):
self._handler = ctypes.c_void_p()
self._num_row = num_row
self._num_col = num_col
self._size = num_col * num_row
mv_lib.MV_NewMatrixTable(num_row, num_col, ctypes.byref(self._handler))
def get(self, row_ids=None):
'''
If row_ids is None, we will return all rows as numpy.narray , e.g.
array([[1, 3], [3, 4]]). Otherwise we will return the data according
to the row_ids
'''
if row_ids is None:
data = np.zeros((self._num_row, self._num_col), dtype=np.dtype("float32"))
mv_lib.MV_GetMatrixTableAll(self._handler, data.ctypes.data_as(C_FLOAT_P), self._size)
return data
else:
row_ids_n = len(row_ids)
int_array_type = ctypes.c_int * row_ids_n
data = np.zeros((row_ids_n, self._num_col), dtype=np.dtype("float32"))
mv_lib.MV_GetMatrixTableByRows(self._handler, data.ctypes.data_as(C_FLOAT_P),
row_ids_n * self._num_col,
int_array_type(*row_ids), row_ids_n)
return data
def add(self, data=None, row_ids=None):
'''
If row_ids is None, we will add all data, and the data
should be a list, e.g. [1, 2, 3, ...]
Otherwise we will add the data according to the row_ids
'''
assert(data is not None)
if not isinstance(data, np.ndarray):
data = np.array(data)
data = data.astype(np.float32)
if row_ids is None:
assert(data.size == self._size)
mv_lib.MV_AddMatrixTableAll(self._handler, data.ctypes.data_as(C_FLOAT_P), self._size)
else:
row_ids_n = len(row_ids)
assert(data.size == row_ids_n * self._num_col)
int_array_type = ctypes.c_int * row_ids_n
mv_lib.MV_AddMatrixTableByRows(self._handler, data.ctypes.data_as(C_FLOAT_P),
row_ids_n * self._num_col,
int_array_type(*row_ids), row_ids_n)

Просмотреть файл

@ -1,14 +1,21 @@
#!/usr/bin/env python
# coding:utf8
import api as mv
import multiverso as mv
import unittest
def setUpModule():
mv.init()
def tearDownModule():
mv.shutdown()
class TestMultiversoTables(unittest.TestCase):
'''
Use the commands below to run test
python -m unittest test.TestMultiversoTables.test_array
python -m unittest test.TestMultiversoTables.test_matrix
$ nosetests
'''
def _test_array(self, size):
@ -24,8 +31,12 @@ class TestMultiversoTables(unittest.TestCase):
mv.barrier()
def test_small_array(self):
# TODO : this is not supported by multiverso because of the size limited
self._test_array(1)
# TODO : this is not supported by multiverso because of the size
# limited. Waiting for the solution of this issue
# https://github.com/Microsoft/multiverso/issues/69
# self._test_array(1)
pass
def test_array(self):
self._test_array(10000)
@ -57,8 +68,6 @@ class TestMultiversoTables(unittest.TestCase):
expected = (row_ids[i] * num_col + j) * count * workers_num * 2
self.assertEqual(expected, actual)
def setUp(self):
mv.init()
def tearDown(self):
mv.shutdown()
if __name__ == '__main__':
unittest.main()

Просмотреть файл

@ -4,8 +4,7 @@
import ctypes
import os
PROJECT_PATH = os.path.abspath(os.path.join(
os.path.dirname(__file__), os.path.pardir, os.path.pardir, os.path.pardir))
PACKAGE_PATH = os.path.abspath(os.path.dirname(__file__))
class Loader(object):
@ -16,7 +15,7 @@ class Loader(object):
def load_lib(cls):
# TODO: write some scripts load .so or .dll
# TODO: adapt it for windows
path = os.path.join(PROJECT_PATH,"build", "src", "libmultiverso.so")
path = os.path.join(PACKAGE_PATH, "libmultiverso.so")
return ctypes.cdll.LoadLibrary(path)
@classmethod

51
binding/python/setup.py Normal file
Просмотреть файл

@ -0,0 +1,51 @@
from setuptools import setup
from setuptools.command.install import install
import shutil
import os
PACKAGE_PATH = os.path.abspath(os.path.dirname(__file__))
PROJECT_PATH = os.path.abspath(os.path.join(PACKAGE_PATH, os.path.pardir, os.path.pardir))
class mv_install(install):
'''
This customized command will place the multiverso.so to the right place.
'''
def run(self):
# TODO: find better way to get the libmultiverso.so
mv_so = os.path.join(PROJECT_PATH, "build", "src", "libmultiverso.so")
if os.path.exists(mv_so):
shutil.copy(mv_so, os.path.join(PACKAGE_PATH, "multiverso"))
install.run(self)
else:
msg = "The libmultiverso.so(" + mv_so + ") can't be found, please"\
" make sure you have followed the guide here"\
"(https://github.com/Microsoft/multiverso/#build) and built"\
"it successfully."
print "\033[93m" + msg + '\033[0m'
def readme():
with open('README.md') as f:
return f.read()
setup(name='multiverso-python',
version='0.1',
long_description=readme(),
description="Multiverso is a parameter server framework for distributed"
" machine learning. This package can leverage multiple machines and GPUs"
" to speed up the python programs.",
url='https://github.com/Microsoft/multiverso',
author='Microsoft',
license='MIT',
packages=['examples.theano', 'examples.theano.lasagne', 'multiverso',
'multiverso.theano_ext', 'multiverso.theano_ext.lasagne_ext'],
install_requires=["theano", "lasagne"],
cmdclass={"install": mv_install},
package_dir={'multiverso': 'multiverso'},
package_data={
'multiverso': ['libmultiverso.so'],
},
include_package_data=True,
zip_safe=False)