- 18 Jun, 2015 1 commit
-
-
Kirill Smelkov authored
On usual kernel, if a file is mmaped, and then memory read, and underlying file implementation return -EIO, the kernel sends SIGBUS to client thread, and if that SIGBUS is not handled the whole client process is terminated with coredump. In bigfile/virtmem.c until now we were doing similar thing - if in vma_on_pagefault() a read request to loadblk() fails - we abort the whole process. This is however not very convenient, because if there is a multithreaded server with each request mapped to thread, and a handling thread for only 1 request fails this way, we kill the whole server process. What could be convenient is to somehow propagate the error to calling thread, e.g. unwinding the stack in a C++-style exceptions way and turning that back to python exception at some point. And in the future we maybe could try to do it. For now we take a small step forward - we can terminate only the thread which caused failed loadblk() - i.e. we still kill the code, without providing it a way to recover, but we kill only the working thread, not the whole process. To test the functionality, we leverage our tfault framework which is now extended to verify not only at which function a testcase dies, but more generally it now examines the traceback (so that we can track coredump to which thread terminated), and also it now verifies exit status code and terminating signal of dying process. NOTE on Linux it is not easy to terminate only 1 thread and produce a coredump for debugging and have right process exit status if e.g. main thread is terminated this way. The reason is Linux hardcodes termination-with-coredump to kill all threads from a process, and even separate processes which happen to share virtual memory layout with the killing thread. So to do such termination, we use hacks and workarounds - see comments in newly introduced __abort_thread(). NOTE2 for getting separate coredump files for several faulting threads /proc/sys/kernel/core_pattern or /proc/sys/kernel/core_uses_pid are your friends. /cc @Tyagov /cc @klaus
-
- 12 Jun, 2015 1 commit
-
-
Kirill Smelkov authored
-
- 02 Jun, 2015 9 commits
-
-
Kirill Smelkov authored
Because numpy.ndarray does not accept it as buffer= argument https://github.com/numpy/numpy/issues/5935 and our memcpy crashes. NOTE if we'll need to use memoryview, we can adapt our memcpy to use array() directly which works with memoryview, as outlined in the above numpy issue.
-
Kirill Smelkov authored
BigArrays can be big - up to 2^64 bytes, and thus in general it is not possible to represent whole BigArray as ndarray view, because address space is usually smaller on 64bit architectures. However users often try to pass BigArrays to numpy functions as-is, and numpy finds a way to convert, or start converting, BigArray to ndarray - via detecting it as a sequence, and extracting elements one-by-one. Which is slooooow. Because of the above, we provide users a well-defined service: - if virtual address space is available - we succeed at creating ndarray view for whole BigArray, without delay and copying. - if not - we report properly the error and give hint how BigArrays have to be processed in chunks. Verifying that big BigArrays cannot be converted to ndarray also tests for behaviour and issues fixed in last 5 patches. /cc @Tyagov /cc @klaus
-
Kirill Smelkov authored
e.g. In [1]: multiply.reduce((1<<30, 1<<30, 1<<30)) Out[1]: 0 instead of In [2]: (1<<30) * (1<<30) * (1<<30) Out[2]: 1237940039285380274899124224 In [3]: 1<<90 Out[3]: 1237940039285380274899124224 also multiply.reduce returns int64, instead of python int: In [4]: type( multiply.reduce([1,2,3]) ) Out[4]: numpy.int64 which also leads to overflow-related problems if we further compute with this value and other integers and results exceeds int64 - it becomes float: In [5]: idx0_stop = 18446744073709551615 In [6]: stride0 = numpy.int64(1) In [7]: byte0_stop = idx0_stop * stride0 In [8]: byte0_stop Out[8]: 1.8446744073709552e+19 and then it becomes a real problem for BigArray.__getitem__() wendelin.core/bigarray/__init__.py:326: RuntimeWarning: overflow encountered in long_scalars page0_min = min(byte0_start, byte0_stop+byte0_stride) // pagesize # TODO -> fileh.pagesize and then > vma0 = self._fileh.mmap(page0_min, page0_max-page0_min+1) E TypeError: integer argument expected, got float ~~~~ So just avoid multiple.reduce() and do our own mul() properly the same way sum() is builtin into python, and we avoid overflow-related problems.
-
Kirill Smelkov authored
We need this commit: http://git.ozlabs.org/?p=ccan;a=commitdiff;h=c38e11b508e52fb2921e67d1123b05d9bef90fd2 or else we segfault on really big arrays allocation instead of getting ENOMEM and reporting it as MemoryError to python.
-
Kirill Smelkov authored
Consider e.g. this for pyvma: 1. in pyfileh_mmap() pyvma is created 2. next fileh_mmap(pyvma, pyfileh, ...) fails 3. we need to deallocate pyvma which was not mapped 4. in pyvma_dealloc() we unmap pyvma unconditionally -> boom. The same story goes for pyfileh dealloc vs not fully constructing it in pyfileh_open().
-
Kirill Smelkov authored
OverflowError when computing slice indices practically means we'll cannot allocate so much address space at next step: In [1]: s = slice(None) In [2]: s.indices(1<<62) Out[2]: (0, 4611686018427387904, 1) In [3]: s.indices(1<<63) --------------------------------------------------------------------------- OverflowError Traceback (most recent call last) <ipython-input-4-5aa549641bc6> in <module>() ----> 1 s.indices(1<<63) OverflowError: cannot fit 'long' into an index-sized integer So translate this OverflowError into MemoryError (preserving message details), because we'll need such "no so much address space" cases to show up as MemoryError in a sooner patch.
-
Kirill Smelkov authored
Currently we always raise RuntimeError for problems, which is more-or-less ok for humans, but soon we'll need to distinguish "no memory" errors from other error conditions in upper layers in code. Introduce helper function for choosing appropriate exception type for an error - MemoryError for when errno=ENOMEM and RuntimeError otherwise, and use it where appropriate. ( Unfortunately Python does not provide such a helper... )
-
Kirill Smelkov authored
As discussion in https://bitbucket.org/pypa/setuptools/issue/313 unveiled, setuptools do not have to carry setuptools.file_finders entrypoint with it in order to support _other_ projects to use .file_finders entry point. In our case it means that is is normal that we have to make sure that the group we are going to register entry-point into, exists. Remove erroneous comments introduced in 11d130d1 (setup: Ensure setuptools.file_finders entry-point group is registered).
-
Kirill Smelkov authored
py2-only syntax introduced in acf7e91d (setup/runcmd: Properly report errors, if running command is missing): File "setup.py", line 168 except Exception, e: ^ SyntaxError: invalid syntax
-
- 01 Jun, 2015 4 commits
-
-
Kirill Smelkov authored
The reason is some people are blocked to access git:// protocol/port because of firewall setup in their environment, and git.ozlabs.org does not provide a way to clone over http(s). We can provide CCAN mirror and we support cloning it over http(s). Also, it makes sense to not depend on thirdparty sites for hosting strongly-related components.
-
Kirill Smelkov authored
-
Kirill Smelkov authored
We currently use subprocess.check_output() for running external command (git), and check_output() checks running command status code, as its name promises: https://github.com/python/cpython/blob/2.7/Lib/subprocess.py#L569 and reports it appropriately to user: https://github.com/python/cpython/blob/2.7/Lib/subprocess.py#L411 but if the command is not found, it is just single error: [Errno 2] No such file or directory which gets output to the log and it is not clear what command failed, or evern if it is from runcmd() call. Redo our runcmd() manually, so that it always report erros with context - what command it was trying to run. The error now becomes: RuntimeError: (['missing-command'],): [Errno 2] No such file or directory /cc @Tyagov
-
Kirill Smelkov authored
-
- 28 May, 2015 4 commits
-
-
Kirill Smelkov authored
If setuptools.file_finders group is not registered, dist.get_entry_map('setuptools.file_finders') returns just {} not connected to entry map, and further modifications of this dict go nowhere (and thus, our git_lsfiles() is not hooked -> sdist fails to produce correct source archive). This is a workaround for setuptools 9.0 dropping `setuptools.file_finders` entrypoint group registration: https://bitbucket.org/pypa/setuptools/commits/f191c8a1225bd58a5fb5aa9abb31b06dc710f0b9#Lsetup.pyF175 https://bitbucket.org/pypa/setuptools/issue/313 issue reported back: https://bitbucket.org/pypa/setuptools/issue/313#comment-18430008
-
Kirill Smelkov authored
It was hanging with NumPy-1.9 before 425dc5d1 (bigarray: Raise IndexError for out-of-bound element access), because of the following correct NumPy commit: https://github.com/numpy/numpy/commit/d36f8227 and in particular https://github.com/numpy/numpy/commit/d36f8227#diff-6d326badc0872de91e025cbfb0be1aafR522 That PySequence_Fast(obj) (with obj being BigArray) creates iterator on top of obj and before our previous IndexError fix in 425dc5d1, this was looping forever. Test explicitly with both NumPy 1.8 and NumPy 1.9, that this construct does not hang. /cc @Tyagov
-
Kirill Smelkov authored
The way BigArray.__getitem__ works for element access is that for e.g. A[i] it translates the request to A[i:i+1] and remembers to lower the dimensionality at scalar index dim_adjust = (0,) so, in full, A[i] is computed this way: A[i] -> A[i:i+1](0,) ( it is done this way to unify code for scalar / slice access in __getitem__ - see 0c826d5c "BigArray: An ndarray-like on top of BigFile memory mappings" ) The code for slice access also has a shortcut - if it sees that slice results in empty array (e.g. for out-of-bound slice), we can avoid spending time to create a file vma mapping only to create empty view on top of it. In 0c826d5c, that optimization, however forgot to apply the "lower the dimensionality" step on top of resulting empty view, and that turned out for not raising IndexError for out-of-bounds scalar access: A = BigArray((10,), uint8) In [1]: A[0] Out[1]: 0 In [2]: A[1] Out[2]: 0 In [3]: A[2] Out[3]: 0 In [4]: A[9] Out[4]: 0 In [5]: A[10] Out[5]: array([], dtype=uint8) NOTE that A[10] returns empty array instead of raising IndexError. So do not forget to apply the "reduce dimensionality" step for empty views, and this way we get proper IndexError (because for empty view, scalar access results in IndexError). NOTE: this bug was also preventing for e.g. list(A) to work, because list(A) internally works this way: l = [] i = iter(A) for _ in i: l.append(_) but iterating would not stop after 10 elements - after array end, _ will be always array([], dtype=uint8), and thus the loop never finished and memory usage grow to infinity. /cc @Tyagov
-
Kirill Smelkov authored
In NumPy speak advanced indexing is picking up arbitrarily requested elemtnts, e.g. a = arange(10) a[[0,3,2]] -> array([0, 3, 2]) The way this indexing schem works is - it creates a new array with len = len(key), and picks up requested elements sequentially into new area. So it is very not the same as creating _view_ to original array data by using basic indexing [1] BigArray does not support advanced indexing, because its main job is to organize an ndarray _view_ backed up by BigFile data and give that view to clients, and then it is up to clients how to use that view with full numpy api available with it. So be explicit, and reject advanced indexing in __getitem__ right at the beginning. [1] http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
-
- 25 May, 2015 3 commits
-
-
Kirill Smelkov authored
-
Kirill Smelkov authored
-
Kirill Smelkov authored
Else, in a clean repo the tests do not build from scratch: $ make test x86_64-linux-gnu-gcc -pthread -g -Wall -D_GNU_SOURCE -std=gnu99 -fplan9-extensions -Wno-declaration-after-statement -Wno-error=declaration-after-statement -Iinclude -I3rdparty/ccan -I3rdparty/include bigfile/tests/test_virtmem.c lib/bug.c lib/utils.c 3rdparty/ccan/ccan/tap/tap.c -o bigfile/tests/test_virtmem.t In file included from include/wendelin/list.h:11:0, from include/wendelin/bigfile/virtmem.h:33, from bigfile/tests/../virtmem.c:23, from bigfile/tests/test_virtmem.c:21: 3rdparty/ccan/ccan/array_size/array_size.h:4:20: fatal error: config.h: No such file or directory #include "config.h" ^ compilation terminated. 3rdparty/ccan/ccan/tap/tap.c:26:20: fatal error: config.h: No such file or directory #include "config.h" ^ compilation terminated. Makefile:99: recipe for target 'bigfile/tests/test_virtmem.t' failed make: *** [bigfile/tests/test_virtmem.t] Error 1
-
- 20 May, 2015 4 commits
-
-
Kirill Smelkov authored
In NumPy, ndarray has .resize() but actually it does a whole array copy into newly allocated larger segment which makes e.g. appending O(n). For BigArray, we don't have that internal constraint NumPy has - to keep the array itself contiguously _stored_ (compare to contiguously _presented_ in memory). So we can have O(1) resize for big arrays. NOTE having O(1) resize, here is how O(δ) append can be done: A # ZBigArray e.g. of shape (N, 3) n = len(A) # lengh of A's major index =N A.resize((n+δ, A.shape[1:])) # add δ new entries ; now len(A) =N+δ A[-δ:] = <new-data> # set data for last new δ entries /cc @klaus
-
Kirill Smelkov authored
test_bigarray_indexing_Nd() contains useful class to have a BigFile connected to ndarray storage. Factor it out so that all tests could use it. BigFile_Data.storeblk() is newly introduced and is currently unused, but will be convenient to have later.
-
Kirill Smelkov authored
-
Kirill Smelkov authored
-
- 14 May, 2015 1 commit
-
-
Kirill Smelkov authored
In 5755a6b3 (Basic setup.py / Makefile to build/install/sdist stuff + bigfile.so skeleton) we overlooked one thing: when tailing from setup.py to make level, we forgot to setup the PYTHON env variable properly, and that leads to changing building with std python. Look e.g. $ python3 setup.py build_ext -i running build_ext python setup.py ll_build_ext --inplace ^^^ which is obviously not correct. Fix it. The tox setup we have setup for testing with multiple interpreters (7af2b2d7 "Tox setup to test things with py27 & py34 and several versions of ZODB") did not caught this, because for every python and environment versions tox initializes separate virtualenv, in which .../bin/python is a link to chosen python, and this way both python and my-selected-for-build-python are the same. Cc: @Tyagov
-
- 29 Apr, 2015 2 commits
-
-
Kirill Smelkov authored
-
Kirill Smelkov authored
For example on Debian 7 Wheezy the kernel (linux 3.2) supports holepunching, because holepunching was added in linux 2.6.38: http://git.kernel.org/linus/79124f18b335172e1916075c633745e12dae1dac but glibc does not provide fallocate mode constants, and compilation fails: gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -D_GNU_SOURCE -I./include -I./3rdparty/ccan -I./3rdparty/include -I/opt/slapgrid/f2a5f59d0d2b521681b9333ee76a2859/parts/python2.7/include/python2.7 -c bigfile/ram_shmfs.c -o build/temp.linux-x86_64-2.7/bigfile/ram_shmfs.o -std=gnu99 -fplan9-extensions -fvisibility=hidden -Wno-declaration-after-statement -Wno-error=declaration-after-statement bigfile/ram_shmfs.c: In function ‘shmfs_drop_memory’: bigfile/ram_shmfs.c:135:31: error: ‘FALLOC_FL_PUNCH_HOLE’ undeclared (first use in this function) bigfile/ram_shmfs.c:135:31: note: each undeclared identifier is reported only once for each function it appears in bigfile/ram_shmfs.c:135:54: error: ‘FALLOC_FL_KEEP_SIZE’ undeclared (first use in this function) error: command 'gcc' failed with exit status 1 Try to fix it via fallbacking to provide the needed defines on older systems ourselves. Cc: Klaus Wölfel <klaus@nexedi.com> Cc: Ivan Tyagov <ivan@tyagov.com>
-
- 15 Apr, 2015 1 commit
-
-
Kirill Smelkov authored
In C99 declaration after statement is ok, and we explicitly compile with -std=gnu99. Python >= 3.4 however adds -Werror=declaration-after-statement even for extension modules irregardless of their compilation flags: https://bugs.python.org/issue21121 and the build fails this way: building 'wendelin.bigfile._bigfile' extension creating build/temp.linux-x86_64-3.4 creating build/temp.linux-x86_64-3.4/bigfile creating build/temp.linux-x86_64-3.4/lib gcc -pthread -Wno-unused-result -Werror=declaration-after-statement -DNDEBUG -fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -DOPENSSL_LOAD_CONF -fPIC -D_GNU_SOURCE -I./include -I./3rdparty/ccan -I./3rdparty/include -I/usr/include/python3.4m -c bigfile/_bigfile.c -o build/temp.linux-x86_64-3.4/bigfile/_bigfile.o -std=gnu99 -fplan9-extensions -fvisibility=hidden bigfile/_bigfile.c: In function ‘pyfile_new’: bigfile/_bigfile.c:679:5: error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement] static char *kw_list[] = {"blksize", NULL}; ^ cc1: some warnings being treated as errors error: command 'gcc' failed with exit status 1 Ensure we turn off this warning and error because we already rely on compiling in C99 mode. Reported-and-tested-by: Ivan Tyagov <ivan@tyagov.com>
-
- 03 Apr, 2015 10 commits
-
-
Kirill Smelkov authored
-
Kirill Smelkov authored
-
Kirill Smelkov authored
This shows how to first generate such arrays (in steps, as every transaction change should fit in memory), and then gather data from whole array using C/Fortran/etc code. It shows how to compute mean via NumPy's ndarray.mean() It also shows that e.g. ndarray.var() wants to create temporaries in size of original ndarray and that would fail, because it does not fit into RAM. ndarray.var() should not need to create such temporaries in principle - all it has to do is to first compute mean, and then compute sum (Xi - <X>)^2 in a loop. <X> is scalar, Xi - is just access to original array. ~~~~ So this also show NumPy can be incrementally improved to avoid creating such temporaries, and then it will work.
-
Kirill Smelkov authored
- for virtual memory subsytem - for ZBigFiles They are not currently great, e.g. for virtmem we have in-kernel overhead of page clearing - in perf profiles, for bigfile_mmap compared to file_read kernel's clear_page_c raises significantly. That is the worker for clearing page memory and we currently cannot avoid that - any memory obtained from kernel (MAP_ANONYMOUS, mmap(file) with hole, etc...) comes pre-initialized to zeros to userspace. This can be seen in the benchmarks as well: file_readbig differs from file_read in only that the latter uses 1 small buffer and the first allocates large memory (cleared by kernel + python does the memset). bigfile/tests/bench_virtmem.py@125::bench_file_mmap_adler32 0.47 (0.86 0.49 0.47) bigfile/tests/bench_virtmem.py@126::bench_file_read_adler32 0.69 (1.11 0.71 0.69) bigfile/tests/bench_virtmem.py@127::bench_file_readbig_adler32 1.41 (1.70 1.42 1.41) bigfile/tests/bench_virtmem.py@128::bench_bigfile_mmap_adler32 1.42 (1.45 1.42 1.51) bigfile/tests/bench_virtmem.py@130::bench_file_mmap_md5 1.52 (1.91 1.54 1.52) bigfile/tests/bench_virtmem.py@131::bench_file_read_md5 1.73 (2.10 1.75 1.73) bigfile/tests/bench_virtmem.py@132::bench_file_readbig_md5 2.44 (2.73 2.46 2.44) bigfile/tests/bench_virtmem.py@133::bench_bigfile_mmap_md5 2.40 (2.48 2.40 2.53) There is MAP_UNINITIALIZED which works only for non-mmu targets and only if explicitly allowed when configuring kernel (off by default). There were patches to disable that pages zeroing, as it gives significant speedup for people's workloads, e.g. [1,2] but all of them did not got merged for security reasons. [1] http://marc.info/?t=132691315900001&r=1&w=2 [2] http://thread.gmane.org/gmane.linux.kernel/548926 ~~~~ For ZBigFile - it is the storage who is dominating in profiles.
-
Kirill Smelkov authored
For this, a small wrapper over py.test is developed (to discover/collect functions to benchmar, etc) and then it runs such functions several times in a boxed enveronment. Benchmarks should be named bench_*.py
-
Kirill Smelkov authored
This is like to BigArray, like ZBigFile is to BigFile (4174b84a "bigfile: BigFile backend to store data in ZODB")
-
Kirill Smelkov authored
I.e. something like numpy.memmap for numpy.ndarray and OS files. The whole bigarray cannot be used as a drop-in replacement for numpy arrays, but BigArray _slices_ are real ndarrays and can be used everywhere ndarray can be used, including in C/Fortran code. Slice size is limited by mapping-size (= address-space size) limit, i.e. to ~ max 127TB on Linux/amd64. Changes to bigarray memory are changes to bigfile memory mapping and as such can be discarded or saved back to bigfile using mapping (= BigFileH) dirty discard/writeout interface. For the same reason the whole amount of changes to memory is limited by amount of physical RAM.
-
Kirill Smelkov authored
This adds transactionality and with e.g. NEO[1] allows to distribute objects to nodes into cluster. We hook into ZODB two-phase commit process as a separate data manager, and synchronize changes to memory, to changes to object only at that time. Alternative would be to get notified on every page change, and mark appropriate object as dirty right at that moment. But I wanted to stay close to filesystem design (we don't get notification for every file change from kernel) - that's why it is done the first way. [1] http://www.neoppod.org/
-
Kirill Smelkov authored
In Python. To demonstrate how backends could be implemented and test system on simple things.
-
Kirill Smelkov authored
Exposes BigFile - this way users can define BigFile backend in Python. Also exposed are BigFile handles, and VMA objects which are results of mmaping.
-