Commit 0da9564c authored by Julien Jerphanion's avatar Julien Jerphanion

Base Experiments with cython+

parents
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
**/*.c
**/*.cpp
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
cdef cypclass Base:
int a
int b
__init__(self, int a, int b):
self.a = a
self.b = b
__init__(self, int a):
self.__init__(a, 0)
__init__(self):
self.__init__(0, 0)
cdef cypclass Derived(Base):
int c
__init__(self, int a, int b, int c):
self.c = c
cpdef cypclass AltDerived(Base):
__init__(self, int a, int b):
self.a = a + b
self.b = b - a
cpdef void test():
cdef Base base = Base(4, 2)
cdef Derived derived1 = Derived(4)
cdef Derived derived2 = Derived(4, 2)
cdef Derived derived3 = Derived(4, 2, 1)
cdef AltDerived alt_derived = AltDerived(4, 2)
print(base.a, base.b)
print(derived1.a, derived1.b, derived1.c)
print(derived2.a, derived2.b, derived2.c)
print(derived3.a, derived3.b, derived3.c)
print(alt_derived.a, alt_derived.b)
cdef cypclass Base:
int base
cdef cypclass Derived1(Base):
int derived1
void setBase(self, int arg):
self.base = arg
cdef cypclass Derived2(Base):
int derived2
void setBase(self, int arg):
self.base = arg
cdef cypclass Diamond(Derived1, Derived2):
int diamond
cdef void printD1(Derived1 d1) with gil:
print(d1.derived1, d1.base)
cdef void printD2(Derived2 d2) with gil:
print(d2.derived2, d2.base)
cpdef void test():
o = Diamond()
o.derived1 = 42
o.derived2 = 4242
Derived1.setBase(o, 4)
Derived2.setBase(o, 2)
printD1(o)
printD2(o)
cdef cypclass A:
int a
int getter(self):
return self.a * 6
int __int__(self):
return self.getter()
__init__(self, int a):
self.a = a - 1
cdef cypclass MyClass:
A cypobj
int number
__init__(self, int a = 0):
self.cypobj = A(a)
self.number = a
__init__(self, A obj):
self.cypobj = obj
self.number = obj.a + 1
int get_A_value(self):
if self.cypobj is not NULL:
return self.cypobj.getter()
else:
return 42
cdef int take_value(MyClass o) nogil:
value = o.get_A_value()
return value
def print_values():
method1_specified = MyClass(2)
method1_default = MyClass()
method2 = new MyClass()
print(take_value(method1_specified),
take_value(method1_default),
take_value(method2))
cdef cypclass Character:
int health
__init__(self, int health):
self.health = health
int update_health(self, int amount):
if -amount > health:
self.health = 0
else:
self.health += amount
return self.health
cdef cypclass Player(Character):
int score
__init__(self, int health):
self.health = health
self.score = 0
Player __iadd__(self, int bonus):
self.score += bonus
return self
void dump(self) with gil:
print("Player Character (health: %d, score: %d)" % (self.health,
self.score))
def main():
cdef Player p
with nogil:
p = Player(10)
p += 2
p.update_health(-1)
p.dump()
from setuptools import setup, Extension
from Cython.Build import build_ext
from glob import glob
# To compile, use
# python setup.py build --inplace
#
extensions = [
Extension(pyx_file.replace(".pyx", ""),
sources=[pyx_file],
language="c++",
)
for pyx_file in sorted(glob("*.pyx"))
]
setup(
name="c",
author="Julien Jerphanion",
author_email="git@jjerphan.xyz",
version='1',
cmdclass={'build_ext': build_ext},
ext_modules=extensions,
install_requires=[
'setuptools>=18.0',
'cython>=0.27.3',
'numpy'
],
classifiers=[
"Intended Audience :: Science/Research",
"Intended Audience :: Developers",
"License :: OSI Approved",
"Programming Language :: C",
"Programming Language :: Python",
"Topic :: Software Development",
"Topic :: Scientific/Engineering",
"Operating System :: POSIX",
"Operating System :: Unix",
"Operating System :: MacOS",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: " "Implementation :: CPython",
],
python_requires=">=3.6",
)
cdef cypclass Singleton
cdef int allocated = 0
cdef Singleton ptr
cdef cypclass Singleton:
Singleton __new__(alloc):
global allocated
global ptr
if not allocated:
allocated = 1
return ptr
cpdef void testSingleton():
o1 = Singleton()
o2 = Singleton()
if o1 is o2 and o1 is ptr:
print("👍")
cpdef cypclass SomeClass:
int a
double b
int __int__(self):
return self.a
double __double__(self):
return self.b
cdef cypclass SomeContainer:
SomeClass some_object
bint __bool__(self):
return self.some_object is not NULL
int __int__(self):
if self:
return <int> self.some_object
else:
return 0
double __double__(self):
if self:
return <double> self.some_object
else:
return 0.0
cpdef void test():
contained = SomeClass()
contained.a = 42
contained.b = 4.2
container = SomeContainer()
container.some_object = contained
print(<bint> container, <int> container, <double> container)
from cython cimport floating
cpdef enum BLAS_Order:
RowMajor # C contiguous
ColMajor # Fortran contiguous
cpdef enum BLAS_Trans:
NoTrans = 110 # correspond to 'n'
Trans = 116 # correspond to 't'
# BLAS Level 1 ################################################################
cdef floating _dot(int, floating*, int, floating*, int) nogil
cdef floating _asum(int, floating*, int) nogil
cdef void _axpy(int, floating, floating*, int, floating*, int) nogil
cdef floating _nrm2(int, floating*, int) nogil
cdef void _copy(int, floating*, int, floating*, int) nogil
cdef void _scal(int, floating, floating*, int) nogil
cdef void _rotg(floating*, floating*, floating*, floating*) nogil
cdef void _rot(int, floating*, int, floating*, int, floating, floating) nogil
# BLAS Level 2 ################################################################
cdef void _gemv(BLAS_Order, BLAS_Trans, int, int, floating, floating*, int,
floating*, int, floating, floating*, int) nogil
cdef void _ger(BLAS_Order, int, int, floating, floating*, int, floating*, int,
floating*, int) nogil
# BLASLevel 3 ################################################################
cdef void _gemm(BLAS_Order, BLAS_Trans, BLAS_Trans, int, int, int, floating,
floating*, int, floating*, int, floating, floating*,
int) nogil
# cython: language_level = 3
from cython cimport floating
from scipy.linalg.cython_blas cimport sdot, ddot
from scipy.linalg.cython_blas cimport sasum, dasum
from scipy.linalg.cython_blas cimport saxpy, daxpy
from scipy.linalg.cython_blas cimport snrm2, dnrm2
from scipy.linalg.cython_blas cimport scopy, dcopy
from scipy.linalg.cython_blas cimport sscal, dscal
from scipy.linalg.cython_blas cimport srotg, drotg
from scipy.linalg.cython_blas cimport srot, drot
from scipy.linalg.cython_blas cimport sgemv, dgemv
from scipy.linalg.cython_blas cimport sger, dger
from scipy.linalg.cython_blas cimport sgemm, dgemm
################
# BLAS Level 1 #
################
cdef floating _dot(int n, floating *x, int incx,
floating *y, int incy) nogil:
"""x.T.y"""
if floating is float:
return sdot(&n, x, &incx, y, &incy)
else:
return ddot(&n, x, &incx, y, &incy)
cpdef _dot_memview(floating[::1] x, floating[::1] y):
return _dot(x.shape[0], &x[0], 1, &y[0], 1)
cdef floating _asum(int n, floating *x, int incx) nogil:
"""sum(|x_i|)"""
if floating is float:
return sasum(&n, x, &incx)
else:
return dasum(&n, x, &incx)
cpdef _asum_memview(floating[::1] x):
return _asum(x.shape[0], &x[0], 1)
cdef void _axpy(int n, floating alpha, floating *x, int incx,
floating *y, int incy) nogil:
"""y := alpha * x + y"""
if floating is float:
saxpy(&n, &alpha, x, &incx, y, &incy)
else:
daxpy(&n, &alpha, x, &incx, y, &incy)
cpdef _axpy_memview(floating alpha, floating[::1] x, floating[::1] y):
_axpy(x.shape[0], alpha, &x[0], 1, &y[0], 1)
cdef floating _nrm2(int n, floating *x, int incx) nogil:
"""sqrt(sum((x_i)^2))"""
if floating is float:
return snrm2(&n, x, &incx)
else:
return dnrm2(&n, x, &incx)
cpdef _nrm2_memview(floating[::1] x):
return _nrm2(x.shape[0], &x[0], 1)
cdef void _copy(int n, floating *x, int incx, floating *y, int incy) nogil:
"""y := x"""
if floating is float:
scopy(&n, x, &incx, y, &incy)
else:
dcopy(&n, x, &incx, y, &incy)
cpdef _copy_memview(floating[::1] x, floating[::1] y):
_copy(x.shape[0], &x[0], 1, &y[0], 1)
cdef void _scal(int n, floating alpha, floating *x, int incx) nogil:
"""x := alpha * x"""
if floating is float:
sscal(&n, &alpha, x, &incx)
else:
dscal(&n, &alpha, x, &incx)
cpdef _scal_memview(floating alpha, floating[::1] x):
_scal(x.shape[0], alpha, &x[0], 1)
cdef void _rotg(floating *a, floating *b, floating *c, floating *s) nogil:
"""Generate plane rotation"""
if floating is float:
srotg(a, b, c, s)
else:
drotg(a, b, c, s)
cpdef _rotg_memview(floating a, floating b, floating c, floating s):
_rotg(&a, &b, &c, &s)
return a, b, c, s
cdef void _rot(int n, floating *x, int incx, floating *y, int incy,
floating c, floating s) nogil:
"""Apply plane rotation"""
if floating is float:
srot(&n, x, &incx, y, &incy, &c, &s)
else:
drot(&n, x, &incx, y, &incy, &c, &s)
cpdef _rot_memview(floating[::1] x, floating[::1] y, floating c, floating s):
_rot(x.shape[0], &x[0], 1, &y[0], 1, c, s)
################
# BLAS Level 2 #
################
cdef void _gemv(BLAS_Order order, BLAS_Trans ta, int m, int n, floating alpha,
floating *A, int lda, floating *x, int incx,
floating beta, floating *y, int incy) nogil:
"""y := alpha * op(A).x + beta * y"""
cdef char ta_ = ta
if order == RowMajor:
ta_ = NoTrans if ta == Trans else Trans
if floating is float:
sgemv(&ta_, &n, &m, &alpha, A, &lda, x, &incx, &beta, y, &incy)
else:
dgemv(&ta_, &n, &m, &alpha, A, &lda, x, &incx, &beta, y, &incy)
else:
if floating is float:
sgemv(&ta_, &m, &n, &alpha, A, &lda, x, &incx, &beta, y, &incy)
else:
dgemv(&ta_, &m, &n, &alpha, A, &lda, x, &incx, &beta, y, &incy)
cpdef _gemv_memview(BLAS_Trans ta, floating alpha, floating[:, :] A,
floating[::1] x, floating beta, floating[::1] y):
cdef:
int m = A.shape[0]
int n = A.shape[1]
BLAS_Order order = ColMajor if A.strides[0] == A.itemsize else RowMajor
int lda = m if order == ColMajor else n
_gemv(order, ta, m, n, alpha, &A[0, 0], lda, &x[0], 1, beta, &y[0], 1)
cdef void _ger(BLAS_Order order, int m, int n, floating alpha, floating *x,
int incx, floating *y, int incy, floating *A, int lda) nogil:
"""A := alpha * x.y.T + A"""
if order == RowMajor:
if floating is float:
sger(&n, &m, &alpha, y, &incy, x, &incx, A, &lda)
else:
dger(&n, &m, &alpha, y, &incy, x, &incx, A, &lda)
else:
if floating is float:
sger(&m, &n, &alpha, x, &incx, y, &incy, A, &lda)
else:
dger(&m, &n, &alpha, x, &incx, y, &incy, A, &lda)
cpdef _ger_memview(floating alpha, floating[::1] x, floating[::] y,
floating[:, :] A):
cdef:
int m = A.shape[0]
int n = A.shape[1]
BLAS_Order order = ColMajor if A.strides[0] == A.itemsize else RowMajor
int lda = m if order == ColMajor else n
_ger(order, m, n, alpha, &x[0], 1, &y[0], 1, &A[0, 0], lda)
################
# BLAS Level 3 #
################
cdef void _gemm(BLAS_Order order, BLAS_Trans ta, BLAS_Trans tb, int m, int n,
int k, floating alpha, floating *A, int lda, floating *B,
int ldb, floating beta, floating *C, int ldc) nogil:
"""C := alpha * op(A).op(B) + beta * C"""
cdef:
char ta_ = ta
char tb_ = tb
if order == RowMajor:
if floating is float:
sgemm(&tb_, &ta_, &n, &m, &k, &alpha, B,
&ldb, A, &lda, &beta, C, &ldc)
else:
dgemm(&tb_, &ta_, &n, &m, &k, &alpha, B,
&ldb, A, &lda, &beta, C, &ldc)
else:
if floating is float:
sgemm(&ta_, &tb_, &m, &n, &k, &alpha, A,
&lda, B, &ldb, &beta, C, &ldc)
else:
dgemm(&ta_, &tb_, &m, &n, &k, &alpha, A,
&lda, B, &ldb, &beta, C, &ldc)
cpdef _gemm_memview(BLAS_Trans ta, BLAS_Trans tb, floating alpha,
floating[:, :] A, floating[:, :] B, floating beta,
floating[:, :] C):
cdef:
int m = A.shape[0] if ta == NoTrans else A.shape[1]
int n = B.shape[1] if tb == NoTrans else B.shape[0]
int k = A.shape[1] if ta == NoTrans else A.shape[0]
int lda, ldb, ldc
BLAS_Order order = ColMajor if A.strides[0] == A.itemsize else RowMajor
if order == RowMajor:
lda = k if ta == NoTrans else m
ldb = n if tb == NoTrans else k
ldc = n
else:
lda = m if ta == NoTrans else k
ldb = k if tb == NoTrans else n
ldc = m
_gemm(order, ta, tb, m, n, k, alpha, &A[0, 0],
lda, &B[0, 0], ldb, beta, &C[0, 0], ldc)
# cython: language_level=3
from cython cimport floating
cimport numpy as np
cdef floating _euclidean_dense_dense(floating*, floating*, int, bint) nogil
cdef floating _euclidean_sparse_dense(floating[::1], int[::1], floating[::1],
floating, bint) nogil
cpdef void _relocate_empty_clusters_dense(
np.ndarray[floating, ndim=2, mode='c'], floating[::1], floating[:, ::1],
floating[:, ::1], floating[::1], int[::1])
cpdef void _relocate_empty_clusters_sparse(
floating[::1], int[::1], int[::1], floating[::1], floating[:, ::1],
floating[:, ::1], floating[::1], int[::1])
cdef void _average_centers(floating[:, ::1], floating[::1])
cdef void _center_shift(floating[:, ::1], floating[:, ::1], floating[::1])
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
# Cython compile instructions
import numpy
from setuptools import setup, Extension
from Cython.Build import build_ext
# To compile, use
# python setup.py build --inplace
#
extensions = [
Extension("kmeans",
sources=["_k_means_fast.pyx"],
include_dirs=[numpy.get_include()],
)
]
setup(
name="kmeans",
cmdclass={'build_ext': build_ext},
ext_modules=extensions,
install_requires=[
'setuptools>=18.0',
'cython>=0.27.3',
'numpy'
],
)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment