diff --git a/.gitignore b/.gitignore index bbcee8a4..dd7182ab 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,6 @@ bin lib lib-static -cufinufftpy/docs/_build -cufinufftpy/docs/_static -cufinufftpy/docs/_templates +python/cufinufft/docs/_build +python/cufinufft/docs/_static +python/cufinufft/docs/_templates diff --git a/Makefile b/Makefile index 2b5503db..2bc0b027 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,6 @@ CUFINUFFTOBJS_64=src/2d/spreadinterp2d.o src/2d/cufinufft2d.o \ src/3d/interp3d_wrapper.o src/3d/cufinufft3d.o \ $(CONTRIBOBJS) CUFINUFFTOBJS_32=$(CUFINUFFTOBJS_64:%.o=%_32.o) -$(info $$CUFINUFFTOBJS_32 is [${CUFINUFFTOBJS_32}]) %_32.o: %.cpp $(HEADERS) diff --git a/README.md b/README.md index 6c765eb9..63fa19e6 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ If not, please ask, we might be able to help. ### Python Wrapper -For those installing from source, this code comes with a Python wrapper module `cufinufftpy`. +For those installing from source, this code comes with a Python wrapper module `cufinufft`. Once you have successfully installed and tested the CUDA library you may run `make python` to manually install the additional Python package. ### Python Package General Python users, or Python software packages which would like to automatically -depend on cufinufftpy using `setuptools` may use a precompiled binary distribution. +depend on cufinufft using `setuptools` may use a precompiled binary distribution. This totally avoids installing from source and managing libraries for supported systems. Because binary distributions are specific to both hardware and software, @@ -48,7 +48,7 @@ we currently only support systems covered by `manylinux2010` that are using CUDA 10.1, 10.2, or 11.0-rc with a compatible GPU. This is currently the most common arrangement. If you have such a system, you may run: -`pip install cufinufftpy` +`pip install cufinufft` For other cases, the Python wrapper should be able to be built from source. We hope to extend this in the future, and have begun work for `manylinux2014`. diff --git a/ci/README.md b/ci/README.md new file mode 100644 index 00000000..f6f4b36b --- /dev/null +++ b/ci/README.md @@ -0,0 +1,37 @@ +# Building Wheels + +Noting how I built the wheels for myself in the future, +and in case it is helpful for when this is automated into the FI CI systems. +Typically these steps would be stages in CICD, and fully automated (up to the review). + +``` +# build the wheel +docker build -f ci/docker/cuda10.1/Dockerfile-x86_64 -t garrettwrong/cufinufft-1.0-manylinux2010 . + +# optionally push it (might take a long time, because I didn't strip/clean the containers, tsk tsk) +docker push garrettwrong/cufinufft-1.0-manylinux2010 + +# Run the container, invoking the build-wheels script to generate the wheels +docker run --gpus all -it -v `pwd`/wheelhouse:/io/wheelhouse -e PLAT=manylinux2010_x86_64 garrettwrong/cufinufft-1.0-manylinux2010 /io/ci/build-wheels.sh + +# Create a source distribution (requires you've built or have lib available) +python setup.py sdist + +# Copy the wheels we care about to the dist folder +cp -v wheelhouse/cufinufft-1.0-cp3*manylinux2010* dist + +# Push to Test PyPI for review/testing +twine upload -r testpypi dist/* + +# Tag release. +## Can do in a repo and push or on manually on GH gui. + +# Review wheels from test index +pip install -i https://test.pypi.org/simple/ --no-deps cufinufft + +# Push to live index +## twine upload dist/* +``` + +Note that because the large size of the library, initially I expect this package will be over the 100MB limit imposed by PyPI. +Generally this just requires pushing a trivial source release, and then requesting an increase. diff --git a/ci/build-wheels.sh b/ci/build-wheels.sh index e70fe63c..fa6426f9 100755 --- a/ci/build-wheels.sh +++ b/ci/build-wheels.sh @@ -12,7 +12,8 @@ function repair_wheel { # Compile wheels -for PYBIN in /opt/python/*/bin; do +for PYBIN in /opt/python/cp3*/bin; do + "${PYBIN}/pip" install -r /io/python/cufinufft/requirements.txt "${PYBIN}/pip" install auditwheel pytest "${PYBIN}/pip" wheel /io/ --no-deps -w wheelhouse/ done @@ -25,7 +26,7 @@ done # Install packages and test -for PYBIN in /opt/python/*/bin/; do - "${PYBIN}/pip" install cufinufftpy -f /io/wheelhouse - pytest /io/ +for PYBIN in /opt/python/cp3*/bin/; do + "${PYBIN}/pip" install cufinufft -f /io/wheelhouse + "${PYBIN}/python" -m pytest /io/python/cufinufft/tests done diff --git a/cufinufftpy/__init__.py b/cufinufftpy/__init__.py deleted file mode 100644 index 0116b720..00000000 --- a/cufinufftpy/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from cufinufftpy.cufinufft import cufinufft - -__all__ = ['cufinufft'] diff --git a/python/cufinufft/__init__.py b/python/cufinufft/__init__.py new file mode 100644 index 00000000..33989ca0 --- /dev/null +++ b/python/cufinufft/__init__.py @@ -0,0 +1,3 @@ +from cufinufft.cufinufft import cufinufft + +__all__ = ['cufinufft'] diff --git a/cufinufftpy/_cufinufft.py b/python/cufinufft/_cufinufft.py similarity index 98% rename from cufinufftpy/_cufinufft.py rename to python/cufinufft/_cufinufft.py index 03a749eb..c213e26b 100644 --- a/cufinufftpy/_cufinufft.py +++ b/python/cufinufft/_cufinufft.py @@ -43,7 +43,7 @@ try: if lib is None: # Find the library. - fh = imp.find_module('cufinufft')[0] + fh = imp.find_module('cufinufftc')[0] # Get the full path for the ctypes loader. full_lib_path = os.path.realpath(fh.name) fh.close() # Be nice and close the open file handle. diff --git a/cufinufftpy/cufinufft.py b/python/cufinufft/cufinufft.py similarity index 86% rename from cufinufftpy/cufinufft.py rename to python/cufinufft/cufinufft.py index 1caec1ba..57dcd89d 100644 --- a/cufinufftpy/cufinufft.py +++ b/python/cufinufft/cufinufft.py @@ -10,16 +10,16 @@ from ctypes import c_int from ctypes import c_void_p -from cufinufftpy._cufinufft import NufftOpts -from cufinufftpy._cufinufft import _default_opts -from cufinufftpy._cufinufft import _make_plan -from cufinufftpy._cufinufft import _make_planf -from cufinufftpy._cufinufft import _set_pts -from cufinufftpy._cufinufft import _set_ptsf -from cufinufftpy._cufinufft import _exec_plan -from cufinufftpy._cufinufft import _exec_planf -from cufinufftpy._cufinufft import _destroy_plan -from cufinufftpy._cufinufft import _destroy_planf +from cufinufft._cufinufft import NufftOpts +from cufinufft._cufinufft import _default_opts +from cufinufft._cufinufft import _make_plan +from cufinufft._cufinufft import _make_planf +from cufinufft._cufinufft import _set_pts +from cufinufft._cufinufft import _set_ptsf +from cufinufft._cufinufft import _exec_plan +from cufinufft._cufinufft import _exec_planf +from cufinufft._cufinufft import _destroy_plan +from cufinufft._cufinufft import _destroy_planf class cufinufft: @@ -144,9 +144,17 @@ def set_pts(self, M, kx, ky=None, kz=None): :param kz: Array of z points. """ - if not (kx.dtype == ky.dtype == kz.dtype == self.dtype): - raise TypeError("cifinufft plan.dtype and " - "kx, ky, kz dtypes do not match.") + if kx.dtype != self.dtype: + raise TypeError("cufinufft plan.dtype and " + "kx dtypes do not match.") + + if ky and ky.dtype != self.dtype: + raise TypeError("cufinufft plan.dtype and " + "ky dtypes do not match.") + + if kz and kz.dtype != self.dtype: + raise TypeError("cufinufft plan.dtype and " + "kz dtypes do not match.") kx = kx.ptr diff --git a/cufinufftpy/docs/Makefile b/python/cufinufft/docs/Makefile similarity index 100% rename from cufinufftpy/docs/Makefile rename to python/cufinufft/docs/Makefile diff --git a/cufinufftpy/docs/conf.py b/python/cufinufft/docs/conf.py similarity index 98% rename from cufinufftpy/docs/conf.py rename to python/cufinufft/docs/conf.py index b0f34691..a5da9fd9 100644 --- a/cufinufftpy/docs/conf.py +++ b/python/cufinufft/docs/conf.py @@ -17,7 +17,7 @@ # -- Project information ----------------------------------------------------- -project = 'cufinufftpy' +project = 'cufinufft' copyright = ('2020 The Simons Foundation, ' 'Melody Shih, Joakim Anden, Garrett Wright.') author = 'Melody Shih, Joakim Anden, Garrett Wright' diff --git a/cufinufftpy/docs/index.rst b/python/cufinufft/docs/index.rst similarity index 68% rename from cufinufftpy/docs/index.rst rename to python/cufinufft/docs/index.rst index ccc4e7a4..7bd1e38b 100644 --- a/cufinufftpy/docs/index.rst +++ b/python/cufinufft/docs/index.rst @@ -1,5 +1,5 @@ -Welcome to cufinufftpy's documentation! -======================================= +Welcome to cufinufft's Python documentation! +============================================== .. automodule:: cufinufft :members: diff --git a/cufinufftpy/docs/make.bat b/python/cufinufft/docs/make.bat similarity index 100% rename from cufinufftpy/docs/make.bat rename to python/cufinufft/docs/make.bat diff --git a/cufinufftpy/requirements.txt b/python/cufinufft/requirements.txt similarity index 100% rename from cufinufftpy/requirements.txt rename to python/cufinufft/requirements.txt diff --git a/cufinufftpy/tests/test_basic.py b/python/cufinufft/tests/test_basic.py similarity index 98% rename from cufinufftpy/tests/test_basic.py rename to python/cufinufft/tests/test_basic.py index d65da6f8..1b159a93 100644 --- a/cufinufftpy/tests/test_basic.py +++ b/python/cufinufft/tests/test_basic.py @@ -3,7 +3,7 @@ import pycuda.autoinit # NOQA:401 import pycuda.gpuarray as gpuarray -from cufinufftpy import cufinufft +from cufinufft import cufinufft import utils diff --git a/cufinufftpy/tests/test_error_checks.py b/python/cufinufft/tests/test_error_checks.py similarity index 94% rename from cufinufftpy/tests/test_error_checks.py rename to python/cufinufft/tests/test_error_checks.py index 42ec5102..a908153e 100644 --- a/cufinufftpy/tests/test_error_checks.py +++ b/python/cufinufft/tests/test_error_checks.py @@ -4,7 +4,7 @@ import pycuda.autoinit # NOQA:401 import pycuda.gpuarray as gpuarray -from cufinufftpy import cufinufft +from cufinufft import cufinufft import utils @@ -39,9 +39,6 @@ def test_set_nu_raises_on_dtype(): plan.set_pts(M, kxyz_gpu_wrong_type[0], kxyz_gpu_wrong_type[1], kxyz_gpu_wrong_type[2]) - plan.set_pts(M, kxyz_gpu[0], - kxyz_gpu[1], kxyz_gpu[2]) - def test_exec_raises_on_dtype(): dtype = np.float32 diff --git a/cufinufftpy/tests/utils.py b/python/cufinufft/tests/utils.py similarity index 100% rename from cufinufftpy/tests/utils.py rename to python/cufinufft/tests/utils.py diff --git a/setup.py b/setup.py index 88bcf81b..3d0a0da3 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools import setup, Extension # Parse the requirements -with open(os.path.join('cufinufftpy', 'requirements.txt'), 'r') as fh: +with open(os.path.join('python/cufinufft', 'requirements.txt'), 'r') as fh: requirements = [item.strip() for item in fh.readlines()] # Sanity check that we can find the CUDA cufinufft libraries before we get too far. @@ -22,7 +22,7 @@ # Python Package Setup setup( - name='cufinufftpy', + name='cufinufft', version='1.0', author='Python interfaces by: Melody Shih, Joakim Anden, Garrett Wright', author_email='yoyoshih13@gmail.com', @@ -30,7 +30,8 @@ description='Python interface to cufinufft', long_description='Python interface to cufinufft (CUDA Flatiron Institute Nonuniform Fast Fourier Transform) library.', license="Apache 2", - packages=['cufinufftpy'], + packages=['cufinufft'], + package_dir={'': 'python'}, install_requires=requirements, # If you'd like to build or alter the docs you may additionally require these. extras_require={ @@ -42,9 +43,9 @@ # that is rpath linked to CUDA library, also decorated (by auditwheel). # Most importantly, pip will manage to install all this stuff in # in places Python can find it (with a little help). - py_modules=['cufinufft'], + py_modules=['cufinufftc'], ext_modules=[ - Extension(name='cufinufft', + Extension(name='cufinufftc', sources=[], libraries=['cufinufft'], library_dirs=['lib']) diff --git a/src/cufinufft.cu b/src/cufinufft.cu index 787f4567..0f7f2960 100644 --- a/src/cufinufft.cu +++ b/src/cufinufft.cu @@ -107,6 +107,8 @@ int CUFINUFFT_MAKEPLAN(int type, int dim, int *nmodes, int iflag, /* allocate the plan structure, assign address to user pointer. */ CUFINUFFT_PLAN d_plan = new CUFINUFFT_PLAN_S; *d_plan_ptr = d_plan; + // Zero out your struct, (sets all pointers to NULL) + memset(d_plan, 0, sizeof(*d_plan)); /* If a user has not supplied their own options, assign defaults for them. */