diff options
| author | CoprDistGit <infra@openeuler.org> | 2023-04-10 08:54:19 +0000 |
|---|---|---|
| committer | CoprDistGit <infra@openeuler.org> | 2023-04-10 08:54:19 +0000 |
| commit | 58742d983e8638b03441fbf7ce597c9eff40500b (patch) | |
| tree | 30d13b0861d78ed2a02636a55f73ab3cb20ecb16 | |
| parent | 269b232c77331bb9e8ad365b1dc0f5f2a4b90ab0 (diff) | |
automatic import of python-cymem
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | python-cymem.spec | 659 | ||||
| -rw-r--r-- | sources | 1 |
3 files changed, 661 insertions, 0 deletions
@@ -0,0 +1 @@ +/cymem-2.0.7.tar.gz diff --git a/python-cymem.spec b/python-cymem.spec new file mode 100644 index 0000000..a26ca1c --- /dev/null +++ b/python-cymem.spec @@ -0,0 +1,659 @@ +%global _empty_manifest_terminate_build 0 +Name: python-cymem +Version: 2.0.7 +Release: 1 +Summary: Manage calls to calloc/free through Cython +License: MIT +URL: https://github.com/explosion/cymem +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/b0/d3/50c90dd821e44ad289653f0029d1690fca82f90df293e77e21443f5ea4fc/cymem-2.0.7.tar.gz + + +%description +<a href="https://explosion.ai"><img src="https://explosion.ai/assets/img/logo.svg" width="125" height="125" align="right" /></a> + +# cymem: A Cython Memory Helper + +cymem provides two small memory-management helpers for Cython. They make it +easy to tie memory to a Python object's life-cycle, so that the memory is freed +when the object is garbage collected. + +[](https://dev.azure.com/explosion-ai/public/_build?definitionId=2) +[](https://pypi.python.org/pypi/cymem) +[](https://anaconda.org/conda-forge/cymem) +[](https://github.com/explosion/wheelwright/releases) + +## Overview + +The most useful is `cymem.Pool`, which acts as a thin wrapper around the calloc +function: + +```python +from cymem.cymem cimport Pool +cdef Pool mem = Pool() +data1 = <int*>mem.alloc(10, sizeof(int)) +data2 = <float*>mem.alloc(12, sizeof(float)) +``` + +The `Pool` object saves the memory addresses internally, and frees them when the +object is garbage collected. Typically you'll attach the `Pool` to some cdef'd +class. This is particularly handy for deeply nested structs, which have +complicated initialization functions. Just pass the `Pool` object into the +initializer, and you don't have to worry about freeing your struct at all — +all of the calls to `Pool.alloc` will be automatically freed when the `Pool` +expires. + +## Installation + +Installation is via [pip](https://pypi.python.org/pypi/pip), and requires [Cython](http://cython.org). Before installing, make sure that your `pip`, `setuptools` and `wheel` are up to date. + +```bash +pip install -U pip setuptools wheel +pip install cymem +``` + +## Example Use Case: An array of structs + +Let's say we want a sequence of sparse matrices. We need fast access, and +a Python list isn't performing well enough. So, we want a C-array or C++ +vector, which means we need the sparse matrix to be a C-level struct — it +can't be a Python class. We can write this easily enough in Cython: + +```python +"""Example without Cymem + +To use an array of structs, we must carefully walk the data structure when +we deallocate it. +""" + +from libc.stdlib cimport calloc, free + +cdef struct SparseRow: + size_t length + size_t* indices + double* values + +cdef struct SparseMatrix: + size_t length + SparseRow* rows + +cdef class MatrixArray: + cdef size_t length + cdef SparseMatrix** matrices + + def __cinit__(self, list py_matrices): + self.length = 0 + self.matrices = NULL + + def __init__(self, list py_matrices): + self.length = len(py_matrices) + self.matrices = <SparseMatrix**>calloc(len(py_matrices), sizeof(SparseMatrix*)) + + for i, py_matrix in enumerate(py_matrices): + self.matrices[i] = sparse_matrix_init(py_matrix) + + def __dealloc__(self): + for i in range(self.length): + sparse_matrix_free(self.matrices[i]) + free(self.matrices) + + +cdef SparseMatrix* sparse_matrix_init(list py_matrix) except NULL: + sm = <SparseMatrix*>calloc(1, sizeof(SparseMatrix)) + sm.length = len(py_matrix) + sm.rows = <SparseRow*>calloc(sm.length, sizeof(SparseRow)) + cdef size_t i, j + cdef dict py_row + cdef size_t idx + cdef double value + for i, py_row in enumerate(py_matrix): + sm.rows[i].length = len(py_row) + sm.rows[i].indices = <size_t*>calloc(sm.rows[i].length, sizeof(size_t)) + sm.rows[i].values = <double*>calloc(sm.rows[i].length, sizeof(double)) + for j, (idx, value) in enumerate(py_row.items()): + sm.rows[i].indices[j] = idx + sm.rows[i].values[j] = value + return sm + + +cdef void* sparse_matrix_free(SparseMatrix* sm) except *: + cdef size_t i + for i in range(sm.length): + free(sm.rows[i].indices) + free(sm.rows[i].values) + free(sm.rows) + free(sm) +``` + +We wrap the data structure in a Python ref-counted class at as low a level as +we can, given our performance constraints. This allows us to allocate and free +the memory in the `__cinit__` and `__dealloc__` Cython special methods. + +However, it's very easy to make mistakes when writing the `__dealloc__` and +`sparse_matrix_free` functions, leading to memory leaks. cymem prevents you from +writing these deallocators at all. Instead, you write as follows: + +```python +"""Example with Cymem. + +Memory allocation is hidden behind the Pool class, which remembers the +addresses it gives out. When the Pool object is garbage collected, all of +its addresses are freed. + +We don't need to write MatrixArray.__dealloc__ or sparse_matrix_free, +eliminating a common class of bugs. +""" +from cymem.cymem cimport Pool + +cdef struct SparseRow: + size_t length + size_t* indices + double* values + +cdef struct SparseMatrix: + size_t length + SparseRow* rows + + +cdef class MatrixArray: + cdef size_t length + cdef SparseMatrix** matrices + cdef Pool mem + + def __cinit__(self, list py_matrices): + self.mem = None + self.length = 0 + self.matrices = NULL + + def __init__(self, list py_matrices): + self.mem = Pool() + self.length = len(py_matrices) + self.matrices = <SparseMatrix**>self.mem.alloc(self.length, sizeof(SparseMatrix*)) + for i, py_matrix in enumerate(py_matrices): + self.matrices[i] = sparse_matrix_init(self.mem, py_matrix) + +cdef SparseMatrix* sparse_matrix_init_cymem(Pool mem, list py_matrix) except NULL: + sm = <SparseMatrix*>mem.alloc(1, sizeof(SparseMatrix)) + sm.length = len(py_matrix) + sm.rows = <SparseRow*>mem.alloc(sm.length, sizeof(SparseRow)) + cdef size_t i, j + cdef dict py_row + cdef size_t idx + cdef double value + for i, py_row in enumerate(py_matrix): + sm.rows[i].length = len(py_row) + sm.rows[i].indices = <size_t*>mem.alloc(sm.rows[i].length, sizeof(size_t)) + sm.rows[i].values = <double*>mem.alloc(sm.rows[i].length, sizeof(double)) + for j, (idx, value) in enumerate(py_row.items()): + sm.rows[i].indices[j] = idx + sm.rows[i].values[j] = value + return sm +``` + +All that the `Pool` class does is remember the addresses it gives out. When the +`MatrixArray` object is garbage-collected, the `Pool` object will also be garbage +collected, which triggers a call to `Pool.__dealloc__`. The `Pool` then frees all of +its addresses. This saves you from walking back over your nested data structures +to free them, eliminating a common class of errors. + +## Custom Allocators + +Sometimes external C libraries use private functions to allocate and free objects, +but we'd still like the laziness of the `Pool`. + +```python +from cymem.cymem cimport Pool, WrapMalloc, WrapFree +cdef Pool mem = Pool(WrapMalloc(priv_malloc), WrapFree(priv_free)) +``` + + +%package -n python3-cymem +Summary: Manage calls to calloc/free through Cython +Provides: python-cymem +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +BuildRequires: python3-cffi +BuildRequires: gcc +BuildRequires: gdb +%description -n python3-cymem +<a href="https://explosion.ai"><img src="https://explosion.ai/assets/img/logo.svg" width="125" height="125" align="right" /></a> + +# cymem: A Cython Memory Helper + +cymem provides two small memory-management helpers for Cython. They make it +easy to tie memory to a Python object's life-cycle, so that the memory is freed +when the object is garbage collected. + +[](https://dev.azure.com/explosion-ai/public/_build?definitionId=2) +[](https://pypi.python.org/pypi/cymem) +[](https://anaconda.org/conda-forge/cymem) +[](https://github.com/explosion/wheelwright/releases) + +## Overview + +The most useful is `cymem.Pool`, which acts as a thin wrapper around the calloc +function: + +```python +from cymem.cymem cimport Pool +cdef Pool mem = Pool() +data1 = <int*>mem.alloc(10, sizeof(int)) +data2 = <float*>mem.alloc(12, sizeof(float)) +``` + +The `Pool` object saves the memory addresses internally, and frees them when the +object is garbage collected. Typically you'll attach the `Pool` to some cdef'd +class. This is particularly handy for deeply nested structs, which have +complicated initialization functions. Just pass the `Pool` object into the +initializer, and you don't have to worry about freeing your struct at all — +all of the calls to `Pool.alloc` will be automatically freed when the `Pool` +expires. + +## Installation + +Installation is via [pip](https://pypi.python.org/pypi/pip), and requires [Cython](http://cython.org). Before installing, make sure that your `pip`, `setuptools` and `wheel` are up to date. + +```bash +pip install -U pip setuptools wheel +pip install cymem +``` + +## Example Use Case: An array of structs + +Let's say we want a sequence of sparse matrices. We need fast access, and +a Python list isn't performing well enough. So, we want a C-array or C++ +vector, which means we need the sparse matrix to be a C-level struct — it +can't be a Python class. We can write this easily enough in Cython: + +```python +"""Example without Cymem + +To use an array of structs, we must carefully walk the data structure when +we deallocate it. +""" + +from libc.stdlib cimport calloc, free + +cdef struct SparseRow: + size_t length + size_t* indices + double* values + +cdef struct SparseMatrix: + size_t length + SparseRow* rows + +cdef class MatrixArray: + cdef size_t length + cdef SparseMatrix** matrices + + def __cinit__(self, list py_matrices): + self.length = 0 + self.matrices = NULL + + def __init__(self, list py_matrices): + self.length = len(py_matrices) + self.matrices = <SparseMatrix**>calloc(len(py_matrices), sizeof(SparseMatrix*)) + + for i, py_matrix in enumerate(py_matrices): + self.matrices[i] = sparse_matrix_init(py_matrix) + + def __dealloc__(self): + for i in range(self.length): + sparse_matrix_free(self.matrices[i]) + free(self.matrices) + + +cdef SparseMatrix* sparse_matrix_init(list py_matrix) except NULL: + sm = <SparseMatrix*>calloc(1, sizeof(SparseMatrix)) + sm.length = len(py_matrix) + sm.rows = <SparseRow*>calloc(sm.length, sizeof(SparseRow)) + cdef size_t i, j + cdef dict py_row + cdef size_t idx + cdef double value + for i, py_row in enumerate(py_matrix): + sm.rows[i].length = len(py_row) + sm.rows[i].indices = <size_t*>calloc(sm.rows[i].length, sizeof(size_t)) + sm.rows[i].values = <double*>calloc(sm.rows[i].length, sizeof(double)) + for j, (idx, value) in enumerate(py_row.items()): + sm.rows[i].indices[j] = idx + sm.rows[i].values[j] = value + return sm + + +cdef void* sparse_matrix_free(SparseMatrix* sm) except *: + cdef size_t i + for i in range(sm.length): + free(sm.rows[i].indices) + free(sm.rows[i].values) + free(sm.rows) + free(sm) +``` + +We wrap the data structure in a Python ref-counted class at as low a level as +we can, given our performance constraints. This allows us to allocate and free +the memory in the `__cinit__` and `__dealloc__` Cython special methods. + +However, it's very easy to make mistakes when writing the `__dealloc__` and +`sparse_matrix_free` functions, leading to memory leaks. cymem prevents you from +writing these deallocators at all. Instead, you write as follows: + +```python +"""Example with Cymem. + +Memory allocation is hidden behind the Pool class, which remembers the +addresses it gives out. When the Pool object is garbage collected, all of +its addresses are freed. + +We don't need to write MatrixArray.__dealloc__ or sparse_matrix_free, +eliminating a common class of bugs. +""" +from cymem.cymem cimport Pool + +cdef struct SparseRow: + size_t length + size_t* indices + double* values + +cdef struct SparseMatrix: + size_t length + SparseRow* rows + + +cdef class MatrixArray: + cdef size_t length + cdef SparseMatrix** matrices + cdef Pool mem + + def __cinit__(self, list py_matrices): + self.mem = None + self.length = 0 + self.matrices = NULL + + def __init__(self, list py_matrices): + self.mem = Pool() + self.length = len(py_matrices) + self.matrices = <SparseMatrix**>self.mem.alloc(self.length, sizeof(SparseMatrix*)) + for i, py_matrix in enumerate(py_matrices): + self.matrices[i] = sparse_matrix_init(self.mem, py_matrix) + +cdef SparseMatrix* sparse_matrix_init_cymem(Pool mem, list py_matrix) except NULL: + sm = <SparseMatrix*>mem.alloc(1, sizeof(SparseMatrix)) + sm.length = len(py_matrix) + sm.rows = <SparseRow*>mem.alloc(sm.length, sizeof(SparseRow)) + cdef size_t i, j + cdef dict py_row + cdef size_t idx + cdef double value + for i, py_row in enumerate(py_matrix): + sm.rows[i].length = len(py_row) + sm.rows[i].indices = <size_t*>mem.alloc(sm.rows[i].length, sizeof(size_t)) + sm.rows[i].values = <double*>mem.alloc(sm.rows[i].length, sizeof(double)) + for j, (idx, value) in enumerate(py_row.items()): + sm.rows[i].indices[j] = idx + sm.rows[i].values[j] = value + return sm +``` + +All that the `Pool` class does is remember the addresses it gives out. When the +`MatrixArray` object is garbage-collected, the `Pool` object will also be garbage +collected, which triggers a call to `Pool.__dealloc__`. The `Pool` then frees all of +its addresses. This saves you from walking back over your nested data structures +to free them, eliminating a common class of errors. + +## Custom Allocators + +Sometimes external C libraries use private functions to allocate and free objects, +but we'd still like the laziness of the `Pool`. + +```python +from cymem.cymem cimport Pool, WrapMalloc, WrapFree +cdef Pool mem = Pool(WrapMalloc(priv_malloc), WrapFree(priv_free)) +``` + + +%package help +Summary: Development documents and examples for cymem +Provides: python3-cymem-doc +%description help +<a href="https://explosion.ai"><img src="https://explosion.ai/assets/img/logo.svg" width="125" height="125" align="right" /></a> + +# cymem: A Cython Memory Helper + +cymem provides two small memory-management helpers for Cython. They make it +easy to tie memory to a Python object's life-cycle, so that the memory is freed +when the object is garbage collected. + +[](https://dev.azure.com/explosion-ai/public/_build?definitionId=2) +[](https://pypi.python.org/pypi/cymem) +[](https://anaconda.org/conda-forge/cymem) +[](https://github.com/explosion/wheelwright/releases) + +## Overview + +The most useful is `cymem.Pool`, which acts as a thin wrapper around the calloc +function: + +```python +from cymem.cymem cimport Pool +cdef Pool mem = Pool() +data1 = <int*>mem.alloc(10, sizeof(int)) +data2 = <float*>mem.alloc(12, sizeof(float)) +``` + +The `Pool` object saves the memory addresses internally, and frees them when the +object is garbage collected. Typically you'll attach the `Pool` to some cdef'd +class. This is particularly handy for deeply nested structs, which have +complicated initialization functions. Just pass the `Pool` object into the +initializer, and you don't have to worry about freeing your struct at all — +all of the calls to `Pool.alloc` will be automatically freed when the `Pool` +expires. + +## Installation + +Installation is via [pip](https://pypi.python.org/pypi/pip), and requires [Cython](http://cython.org). Before installing, make sure that your `pip`, `setuptools` and `wheel` are up to date. + +```bash +pip install -U pip setuptools wheel +pip install cymem +``` + +## Example Use Case: An array of structs + +Let's say we want a sequence of sparse matrices. We need fast access, and +a Python list isn't performing well enough. So, we want a C-array or C++ +vector, which means we need the sparse matrix to be a C-level struct — it +can't be a Python class. We can write this easily enough in Cython: + +```python +"""Example without Cymem + +To use an array of structs, we must carefully walk the data structure when +we deallocate it. +""" + +from libc.stdlib cimport calloc, free + +cdef struct SparseRow: + size_t length + size_t* indices + double* values + +cdef struct SparseMatrix: + size_t length + SparseRow* rows + +cdef class MatrixArray: + cdef size_t length + cdef SparseMatrix** matrices + + def __cinit__(self, list py_matrices): + self.length = 0 + self.matrices = NULL + + def __init__(self, list py_matrices): + self.length = len(py_matrices) + self.matrices = <SparseMatrix**>calloc(len(py_matrices), sizeof(SparseMatrix*)) + + for i, py_matrix in enumerate(py_matrices): + self.matrices[i] = sparse_matrix_init(py_matrix) + + def __dealloc__(self): + for i in range(self.length): + sparse_matrix_free(self.matrices[i]) + free(self.matrices) + + +cdef SparseMatrix* sparse_matrix_init(list py_matrix) except NULL: + sm = <SparseMatrix*>calloc(1, sizeof(SparseMatrix)) + sm.length = len(py_matrix) + sm.rows = <SparseRow*>calloc(sm.length, sizeof(SparseRow)) + cdef size_t i, j + cdef dict py_row + cdef size_t idx + cdef double value + for i, py_row in enumerate(py_matrix): + sm.rows[i].length = len(py_row) + sm.rows[i].indices = <size_t*>calloc(sm.rows[i].length, sizeof(size_t)) + sm.rows[i].values = <double*>calloc(sm.rows[i].length, sizeof(double)) + for j, (idx, value) in enumerate(py_row.items()): + sm.rows[i].indices[j] = idx + sm.rows[i].values[j] = value + return sm + + +cdef void* sparse_matrix_free(SparseMatrix* sm) except *: + cdef size_t i + for i in range(sm.length): + free(sm.rows[i].indices) + free(sm.rows[i].values) + free(sm.rows) + free(sm) +``` + +We wrap the data structure in a Python ref-counted class at as low a level as +we can, given our performance constraints. This allows us to allocate and free +the memory in the `__cinit__` and `__dealloc__` Cython special methods. + +However, it's very easy to make mistakes when writing the `__dealloc__` and +`sparse_matrix_free` functions, leading to memory leaks. cymem prevents you from +writing these deallocators at all. Instead, you write as follows: + +```python +"""Example with Cymem. + +Memory allocation is hidden behind the Pool class, which remembers the +addresses it gives out. When the Pool object is garbage collected, all of +its addresses are freed. + +We don't need to write MatrixArray.__dealloc__ or sparse_matrix_free, +eliminating a common class of bugs. +""" +from cymem.cymem cimport Pool + +cdef struct SparseRow: + size_t length + size_t* indices + double* values + +cdef struct SparseMatrix: + size_t length + SparseRow* rows + + +cdef class MatrixArray: + cdef size_t length + cdef SparseMatrix** matrices + cdef Pool mem + + def __cinit__(self, list py_matrices): + self.mem = None + self.length = 0 + self.matrices = NULL + + def __init__(self, list py_matrices): + self.mem = Pool() + self.length = len(py_matrices) + self.matrices = <SparseMatrix**>self.mem.alloc(self.length, sizeof(SparseMatrix*)) + for i, py_matrix in enumerate(py_matrices): + self.matrices[i] = sparse_matrix_init(self.mem, py_matrix) + +cdef SparseMatrix* sparse_matrix_init_cymem(Pool mem, list py_matrix) except NULL: + sm = <SparseMatrix*>mem.alloc(1, sizeof(SparseMatrix)) + sm.length = len(py_matrix) + sm.rows = <SparseRow*>mem.alloc(sm.length, sizeof(SparseRow)) + cdef size_t i, j + cdef dict py_row + cdef size_t idx + cdef double value + for i, py_row in enumerate(py_matrix): + sm.rows[i].length = len(py_row) + sm.rows[i].indices = <size_t*>mem.alloc(sm.rows[i].length, sizeof(size_t)) + sm.rows[i].values = <double*>mem.alloc(sm.rows[i].length, sizeof(double)) + for j, (idx, value) in enumerate(py_row.items()): + sm.rows[i].indices[j] = idx + sm.rows[i].values[j] = value + return sm +``` + +All that the `Pool` class does is remember the addresses it gives out. When the +`MatrixArray` object is garbage-collected, the `Pool` object will also be garbage +collected, which triggers a call to `Pool.__dealloc__`. The `Pool` then frees all of +its addresses. This saves you from walking back over your nested data structures +to free them, eliminating a common class of errors. + +## Custom Allocators + +Sometimes external C libraries use private functions to allocate and free objects, +but we'd still like the laziness of the `Pool`. + +```python +from cymem.cymem cimport Pool, WrapMalloc, WrapFree +cdef Pool mem = Pool(WrapMalloc(priv_malloc), WrapFree(priv_free)) +``` + + +%prep +%autosetup -n cymem-2.0.7 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-cymem -f filelist.lst +%dir %{python3_sitearch}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Mon Apr 10 2023 Python_Bot <Python_Bot@openeuler.org> - 2.0.7-1 +- Package Spec generated @@ -0,0 +1 @@ +f9f8b455bb055061e7e0133676556136 cymem-2.0.7.tar.gz |
