278 lines
6.3 KiB
Python
278 lines
6.3 KiB
Python
import time
|
|
import glob
|
|
import io
|
|
import os
|
|
import numpy
|
|
import numpy.typing
|
|
import functools
|
|
import pathlib
|
|
import threading
|
|
import cython
|
|
import datetime
|
|
|
|
from typing import (Any, Optional, TypeVar, Type, cast)
|
|
# from scoping import scoping as s
|
|
|
|
def test(
|
|
_id: int,
|
|
T: float,
|
|
a: numpy.ndarray[Any, numpy.dtype[numpy.int32]],
|
|
) -> None:
|
|
with cython.nogil:
|
|
#if True:
|
|
started_at = datetime.datetime.now()
|
|
print('started')
|
|
def elapsed() -> float:
|
|
return (datetime.datetime.now() - started_at).total_seconds()
|
|
#a = 0
|
|
while elapsed() < T:
|
|
#a += 1
|
|
for k in range(1024 * 1024):
|
|
a[_id] += 1
|
|
|
|
print(['done', started_at, elapsed(), a[_id]])
|
|
|
|
M = TypeVar('M', bound=Type[Any])
|
|
|
|
def build(content: str, module: M) -> M:
|
|
import pathlib
|
|
import tempfile
|
|
import hashlib
|
|
import Cython.Build.Inline
|
|
|
|
sha256sum = hashlib.sha256(content.encode('utf-8')).digest().hex()
|
|
|
|
output_dir = (pathlib.Path('.') / 'tmp' / 'cython' / sha256sum).absolute()
|
|
|
|
|
|
if not output_dir.exists() or True:
|
|
os.makedirs(str(output_dir), exist_ok=True)
|
|
|
|
source_path = output_dir / ('_%s.pyx' % sha256sum)
|
|
if not source_path.exists():
|
|
with io.open(str(source_path), 'w') as f:
|
|
f.write(content)
|
|
|
|
t1 = Cython.Build.Inline._get_build_extension()
|
|
t1.extensions = Cython.Build.cythonize(str(source_path))
|
|
t1.build_temp = str(pathlib.Path('/'))
|
|
t1.build_lib = str(output_dir)
|
|
#t2 = Cython.Build.Inline.Extension(
|
|
# name=sha256sum,
|
|
#)
|
|
t1.run()
|
|
|
|
return cast(
|
|
M,
|
|
Cython.Build.Inline.load_dynamic(
|
|
'_%s' % sha256sum,
|
|
glob.glob(
|
|
str(output_dir / ('_%s*.so' % sha256sum))
|
|
)[0]
|
|
)
|
|
)
|
|
|
|
raise NotImplementedError
|
|
|
|
def mypyc_build(file_path: pathlib.Path) -> Any:
|
|
import pathlib
|
|
import tempfile
|
|
import hashlib
|
|
import mypyc.build
|
|
import Cython.Build.Inline
|
|
|
|
assert isinstance(file_path, pathlib.Path)
|
|
|
|
#sha256sum = hashlib.sha256(content.encode('utf-8')).digest().hex()
|
|
|
|
#output_dir = (pathlib.Path('.') / 'tmp' / 'cython' / sha256sum).absolute()
|
|
output_dir = pathlib.Path('.') / 'tmp' / 'mypyc'
|
|
sha256sum = file_path.stem
|
|
lib_pattern = file_path.parent / ('%s.cpython*.so' % sha256sum)
|
|
lib_dir = pathlib.Path('.')
|
|
|
|
|
|
def lib_path_glob(path: str | pathlib.Path) -> Optional[pathlib.Path]:
|
|
res : list[str] = glob.glob(str(path))
|
|
|
|
if len(res) == 0:
|
|
return None
|
|
else:
|
|
return pathlib.Path(res[0])
|
|
|
|
need_build : bool = False
|
|
|
|
lib_path : Optional[pathlib.Path] = None
|
|
|
|
lib_path = lib_path_glob(lib_pattern)
|
|
|
|
if not lib_path is None:
|
|
t2 = file_path.stat()
|
|
t3 = lib_path.stat()
|
|
if t3.st_mtime < t2.st_mtime:
|
|
need_build = True
|
|
|
|
del t2
|
|
del t3
|
|
else:
|
|
need_build = True
|
|
|
|
|
|
if need_build:
|
|
for o in [
|
|
output_dir,
|
|
output_dir / 'build' / file_path.parent,
|
|
]:
|
|
os.makedirs(
|
|
str(o),
|
|
exist_ok=True
|
|
)
|
|
#source_path = output_dir / ('_%s.py' % sha256sum)
|
|
source_path = file_path
|
|
#with io.open(str(source_path), 'w') as f:
|
|
# f.write(content)
|
|
|
|
t1 = Cython.Build.Inline._get_build_extension()
|
|
t1.extensions = mypyc.build.mypycify(
|
|
[str(source_path)],
|
|
target_dir=str(output_dir / 'build')
|
|
)
|
|
t1.build_temp = str(output_dir)
|
|
t1.build_lib = str(lib_dir)
|
|
#t2 = Cython.Build.Inline.Extension(
|
|
# name=sha256sum,
|
|
#)
|
|
t1.run()
|
|
|
|
lib_path = lib_path_glob(lib_pattern)
|
|
|
|
return Cython.Build.Inline.load_dynamic(
|
|
#'_%s' % sha256sum,
|
|
#t1.extensions[0].name,
|
|
file_path.stem,
|
|
str(lib_path),
|
|
)
|
|
|
|
raise NotImplementedError
|
|
|
|
class Source:
|
|
@staticmethod
|
|
def test2(
|
|
_a : numpy.ndarray[Any, numpy.dtype[numpy.int64]],
|
|
_id : numpy.dtype[numpy.int32] | int,
|
|
T : float=16
|
|
) -> int:
|
|
raise NotImplementedError
|
|
|
|
|
|
source = build(r'''
|
|
cimport cython
|
|
|
|
@cython.boundscheck(False)
|
|
@cython.wraparound(False)
|
|
def test4(int[:] a, int[:] b):
|
|
cdef int N = a.shape[0]
|
|
assert N == b.shape[0]
|
|
|
|
with cython.nogil:
|
|
for i in range(N):
|
|
a[i] += b[i]
|
|
return N
|
|
|
|
import datetime
|
|
|
|
def elapsed(started_at: datetime.datetime):
|
|
res = (datetime.datetime.now() - started_at).total_seconds()
|
|
|
|
return res
|
|
|
|
@cython.boundscheck(False) # Deactivate bounds checking
|
|
@cython.wraparound(False) # Deactivate negative indexing.
|
|
def has_time(started_at: datetime.datetime, T: float):
|
|
t1 = elapsed(started_at)
|
|
|
|
res = t1 < T
|
|
|
|
return res
|
|
|
|
@cython.boundscheck(False)
|
|
@cython.wraparound(False)
|
|
def test2(long long [:] _a, int _id, double T=16) -> int:
|
|
started_at = datetime.datetime.now()
|
|
|
|
print('started')
|
|
|
|
cdef int C = 1;
|
|
|
|
cdef int cond;
|
|
|
|
with cython.nogil:
|
|
#if True:
|
|
#a = 0
|
|
while True:
|
|
|
|
with cython.gil:
|
|
cond = has_time(started_at, T)
|
|
#cond = 0
|
|
|
|
if cond != 1:
|
|
break
|
|
|
|
#a += 1
|
|
for k in range(1024 * 1024 * 1024):
|
|
_a[_id] += C
|
|
|
|
print(['done', started_at, elapsed(started_at), _a[_id]])
|
|
|
|
return _a[_id]
|
|
|
|
''', Source)
|
|
|
|
def test_cython(N: int=4, T:int=16) -> None:
|
|
#a = [0] * N
|
|
a = numpy.zeros((N,), dtype=numpy.int64)
|
|
|
|
t = [
|
|
threading.Thread(
|
|
target=functools.partial(
|
|
source.test2,
|
|
a,
|
|
k,
|
|
T,
|
|
)
|
|
)
|
|
for k in range(N)
|
|
]
|
|
|
|
for o in t:
|
|
o.start()
|
|
for o in t:
|
|
o.join()
|
|
|
|
#cython_module['test2'](a, 0)
|
|
|
|
def test_mypyc(N: int=4, W:int=35) -> None:
|
|
cython2 = mypyc_build(
|
|
(pathlib.Path(__file__).parent / 'cython2.py').relative_to(
|
|
pathlib.Path.cwd()
|
|
)
|
|
)
|
|
|
|
# from .cython2 import fib
|
|
|
|
#a = [0] * N
|
|
t = [
|
|
threading.Thread(
|
|
target=functools.partial(
|
|
cython2.fib,
|
|
W,
|
|
)
|
|
)
|
|
for k in range(N)
|
|
]
|
|
|
|
for o in t:
|
|
o.start()
|
|
for o in t:
|
|
o.join()
|