diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dddca26571f9f260017a02ba11b4c1abe06f008a..d347af93e79ced925088583b5799848af222a10d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,6 +6,7 @@ - echo "CL_ENABLE_GL = True" > siteconf.py - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-and-test-py-project.sh - ". ./build-and-test-py-project.sh" + allow_failure: true tags: - python2.7 - amd-cl-cpu @@ -33,6 +34,7 @@ Python 3.5 AMD CPU: - export EXTRA_INSTALL="numpy mako" - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-and-test-py-project.sh - ". ./build-and-test-py-project.sh" + allow_failure: true tags: - python3.5 - amd-cl-cpu @@ -46,6 +48,7 @@ Python 2.6 AMD CPU: - export EXTRA_INSTALL="numpy mako" - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-and-test-py-project.sh - ". ./build-and-test-py-project.sh" + allow_failure: true tags: - python2.6 - amd-cl-cpu @@ -85,6 +88,7 @@ Python 3.5 AMD GPU: - export EXTRA_INSTALL="numpy mako" - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-and-test-py-project.sh - ". ./build-and-test-py-project.sh" + allow_failure: true tags: - python3.5 - amd-fiji diff --git a/doc/runtime_memory.rst b/doc/runtime_memory.rst index f23a29ae4912173f1019b15fc53cc629fd78ab2f..94d7d1979695f3e6185f839f1f824fb6b6faec5c 100644 --- a/doc/runtime_memory.rst +++ b/doc/runtime_memory.rst @@ -321,6 +321,15 @@ Mapping Memory into Host Address Space .. versionchanged:: 2013.2 Added *strides* argument. + Sample usage:: + + mapped_buf = cl.enqueue_map_buffer(queue, buf, ...) + with mapped_buf.base: + # work with mapped_buf + ... + + # memory will be unmapped here + .. function:: enqueue_map_image(queue, buf, flags, origin, region, shape, dtype, order="C", strides=None, wait_for=None, is_blocking=True) |explain-waitfor| diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index b85400cb88ace1effff48580b69bc046358e9cfc..62f9edbfa2e903cd8143a388f63832692e18314f 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -144,6 +144,10 @@ class _CArray(object): def _generic_info_to_python(info): type_ = _ffi_pystr(info.type) + + if info.free_type: + _lib.free_pointer(info.type) + value = _ffi.cast(type_, info.value) if info.opaque_class != _lib.CLASS_NONE: @@ -200,7 +204,7 @@ def _generic_info_to_python(info): ret = list(value) else: ret = value[0] - if info.dontfree == 0: + if info.free_value: _lib.free_pointer(info.value) return ret @@ -941,10 +945,12 @@ class MemoryObject(MemoryObjectHolder): # {{{ MemoryMap class MemoryMap(_Common): - """" - .. automethod:: release - + """ This class may also be used as a context manager in a ``with`` statement. + The memory corresponding to this object will be unmapped when + this object is deleted or :meth:`release` is called. + + .. automethod:: release """ @classmethod diff --git a/pyopencl/version.py b/pyopencl/version.py index 751a8cfcb1695d46d5374083d140b09f9ee9d8e0..0335619dfda4daa6f1f9d672ebdf857f97844af1 100644 --- a/pyopencl/version.py +++ b/pyopencl/version.py @@ -1,3 +1,3 @@ -VERSION = (2017, 1, 2) +VERSION = (2017, 2) VERSION_STATUS = "" VERSION_TEXT = ".".join(str(x) for x in VERSION) + VERSION_STATUS diff --git a/src/c_wrapper/clhelper.h b/src/c_wrapper/clhelper.h index c88c00519b899f134a74066e2c9fa9cff547fee7..d0aff85c329ead7956ed2621fa4c00a1c887ab7c 100644 --- a/src/c_wrapper/clhelper.h +++ b/src/c_wrapper/clhelper.h @@ -86,17 +86,27 @@ get_vec_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name, #define pyopencl_get_vec_info(type, what, ...) \ get_vec_info<type>(clGet##what##Info, "clGet" #what "Info", __VA_ARGS__) +inline generic_info make_generic_info(class_t opaque_class, const char *type, bool free_type, void *value, bool free_value) +{ + generic_info result; + result.opaque_class = opaque_class; + result.type = type; + result.free_type = free_type; + result.value = value; + result.free_value = free_value; + return result; +} + template<typename T> PYOPENCL_USE_RESULT static PYOPENCL_INLINE generic_info convert_array_info(const char *tname, pyopencl_buf<T> &buf) { - generic_info info; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; - info.type = _copy_str(std::string(tname) + "[" + - tostring(buf.len()) + "]"); - info.value = buf.release(); - return info; + return make_generic_info( + CLASS_NONE, + _copy_str(std::string(tname) + "[" + tostring(buf.len()) + "]"), + true, + buf.release(), + true); } template<typename T> @@ -116,12 +126,12 @@ template<typename CLObj, typename T> PYOPENCL_USE_RESULT static PYOPENCL_INLINE generic_info convert_opaque_array_info(T &&buf) { - generic_info info; - info.dontfree = 0; - info.opaque_class = CLObj::class_id; - info.type = _copy_str(std::string("void*[") + tostring(buf.len()) + "]"); - info.value = buf_to_base<CLObj>(std::forward<T>(buf)).release(); - return info; + return make_generic_info( + CLObj::class_id, + _copy_str(std::string("void*[") + tostring(buf.len()) + "]"), + true, + buf_to_base<CLObj>(std::forward<T>(buf)).release(), + true); } #define pyopencl_get_opaque_array_info(cls, what, ...) \ convert_opaque_array_info<cls>( \ @@ -134,16 +144,13 @@ get_opaque_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name, { typename CLObj::cl_type param_value; call_guarded(func, name, args..., size_arg(param_value), nullptr); - generic_info info; - info.dontfree = 0; - info.opaque_class = CLObj::class_id; - info.type = "void *"; + void *value; if (param_value) { - info.value = (void*)(new CLObj(param_value, /*retain*/ true)); + value = (void*)(new CLObj(param_value, /*retain*/ true)); } else { - info.value = nullptr; + value = nullptr; } - return info; + return make_generic_info(CLObj::class_id, "void *", false, value, true); } #define pyopencl_get_opaque_info(clobj, what, ...) \ get_opaque_info<clobj>(clGet##what##Info, \ @@ -158,12 +165,7 @@ get_str_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name, call_guarded(func, name, args..., 0, nullptr, buf_arg(size)); pyopencl_buf<char> param_value(size); call_guarded(func, name, args..., param_value, buf_arg(size)); - generic_info info; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; - info.type = "char*"; - info.value = (void*)param_value.release(); - return info; + return make_generic_info(CLASS_NONE, "char*", false, (void*)param_value.release(), true); } #define pyopencl_get_str_info(what, ...) \ get_str_info(clGet##what##Info, "clGet" #what "Info", __VA_ARGS__) @@ -175,12 +177,7 @@ get_int_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name, { T value; call_guarded(func, name, args..., size_arg(value), nullptr); - generic_info info; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; - info.type = tpname; - info.value = cl_memdup(&value); - return info; + return make_generic_info(CLASS_NONE, tpname, false, cl_memdup(&value), true); } #define pyopencl_get_int_info(type, what, ...) \ get_int_info<type>(clGet##what##Info, "clGet" #what "Info", \ diff --git a/src/c_wrapper/context.cpp b/src/c_wrapper/context.cpp index f2478fd73a54c11dbed830f6eace3e57f9ace215..0fe48554f954e46dad0ef5561932a9cb9fdb75ff 100644 --- a/src/c_wrapper/context.cpp +++ b/src/c_wrapper/context.cpp @@ -56,15 +56,12 @@ context::get_info(cl_uint param_name) const if (key == 0) break; cl_context_properties value = result[i * 2 + 1]; - generic_info &info = py_result[i]; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; switch (key) { case CL_CONTEXT_PLATFORM: - info.opaque_class = CLASS_PLATFORM; - info.type = "void *"; - info.value = new platform( - reinterpret_cast<cl_platform_id>(value)); + py_result[i] = make_generic_info( + CLASS_PLATFORM, + "void *", false, + new platform(reinterpret_cast<cl_platform_id>(value)), true); break; #if defined(PYOPENCL_GL_SHARING_VERSION) && (PYOPENCL_GL_SHARING_VERSION >= 1) @@ -77,12 +74,13 @@ context::get_info(cl_uint param_name) const case CL_WGL_HDC_KHR: case CL_CGL_SHAREGROUP_KHR: #endif - info.type = "intptr_t *"; - info.value = (void*)value; - // we do not own this object - info.dontfree = 1; - break; - + py_result[i] = make_generic_info( + CLASS_NONE, + "intptr_t *", false, + (void*)value, + // we do not own this object + false); + break; #endif default: throw clerror("Context.get_info", CL_INVALID_VALUE, diff --git a/src/c_wrapper/device.cpp b/src/c_wrapper/device.cpp index 7bc7fd5a690b6a092bce17f5b28f15cb436a5c49..16edaf34c7be2934e6350855a1788bf1311a6641 100644 --- a/src/c_wrapper/device.cpp +++ b/src/c_wrapper/device.cpp @@ -37,12 +37,7 @@ get_device_topology_amd(ArgTypes&&... args) cl_device_topology_amd value; const char * fname = "clGetDeviceInfo"; call_guarded(clGetDeviceInfo, fname, args..., size_arg(value), nullptr); - generic_info info; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; - info.type = tpname; - info.value = cl_memdup(&value); - return info; + return make_generic_info(CLASS_NONE, tpname, false, cl_memdup(&value), true); } #define pyopencl_get_device_topology_amd(...) get_device_topology_amd(__VA_ARGS__) diff --git a/src/c_wrapper/program.cpp b/src/c_wrapper/program.cpp index d50d96802830269c0b8e35bbda4b85fe97e644c7..a0535c06a9d33abdf4cb91d93a87d6141bd7407a 100644 --- a/src/c_wrapper/program.cpp +++ b/src/c_wrapper/program.cpp @@ -54,11 +54,12 @@ program::get_info(cl_uint param) const } pyopencl_buf<generic_info> gis(sizes.len()); for (size_t i = 0;i < sizes.len();i++) { - gis[i].value = result_ptrs[i]; - gis[i].dontfree = 0; - gis[i].opaque_class = CLASS_NONE; - gis[i].type = _copy_str(std::string("char[") + - tostring(sizes[i]) + "]"); + gis[i] = make_generic_info( + CLASS_NONE, + _copy_str(std::string("char[") + tostring(sizes[i]) + "]"), + true, + result_ptrs[i], + true); } return pyopencl_convert_array_info(generic_info, gis); } diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h index 746c1b9d85659564a50fdbfdc1890d75d678073d..184cd001f5157661aa0a70732e06fc327694c32b 100644 --- a/src/c_wrapper/wrap_cl_core.h +++ b/src/c_wrapper/wrap_cl_core.h @@ -43,8 +43,9 @@ typedef enum { typedef struct { class_t opaque_class; const char *type; + bool free_type; void *value; - int dontfree; + bool free_value; } generic_info; // }}}