def allocate(self, nbytes): buf = cl.Buffer(self.context, self.mem_flags, nbytes) # Make sure the buffer gets allocated right here and right now. # This looks (and is) expensive. But immediate allocators # have their main use in memory pools, whose basic assumption # is that allocation is too expensive anyway--but they rely # on exact 'out-of-memory' information. from pyopencl.cffi_cl import _enqueue_write_buffer _enqueue_write_buffer( self.queue, buf, _zero[:min(len(_zero), nbytes)], is_blocking=False) # No need to wait for completion here. clWaitForEvents (e.g.) # cannot return mem object allocation failures. This implies that # the buffer is faulted onto the device on enqueue. return buf
def enqueue_copy(queue, dest, src, **kwargs): """Copy from :class:`Image`, :class:`Buffer` or the host to :class:`Image`, :class:`Buffer` or the host. (Note: host-to-host copies are unsupported.) The following keyword arguments are available: :arg wait_for: (optional, default empty) :arg is_blocking: Wait for completion. Defaults to *True*. (Available on any copy involving host memory) :return: A :class:`NannyEvent` if the transfer involved a host-side buffer, otherwise an :class:`Event`. .. note:: Two types of 'buffer' occur in the arguments to this function, :class:`Buffer` and 'host-side buffers'. The latter are defined by Python and commonly called `buffer objects <https://docs.python.org/3.4/c-api/buffer.html>`_. :mod:`numpy` arrays are a very common example. Make sure to always be clear on whether a :class:`Buffer` or a Python buffer object is needed. .. ------------------------------------------------------------------------ .. rubric :: Transfer :class:`Buffer` ↔ host .. ------------------------------------------------------------------------ :arg device_offset: offset in bytes (optional) .. note:: The size of the transfer is controlled by the size of the of the host-side buffer. If the host-side buffer is a :class:`numpy.ndarray`, you can control the transfer size by transfering into a smaller 'view' of the target array, like this:: cl.enqueue_copy(queue, large_dest_numpy_array[:15], src_buffer) .. ------------------------------------------------------------------------ .. rubric :: Transfer :class:`Buffer` ↔ :class:`Buffer` .. ------------------------------------------------------------------------ :arg byte_count: (optional) If not specified, defaults to the size of the source in versions 2012.x and earlier, and to the minimum of the size of the source and target from 2013.1 on. :arg src_offset: (optional) :arg dest_offset: (optional) .. ------------------------------------------------------------------------ .. rubric :: Rectangular :class:`Buffer` ↔ host transfers (CL 1.1 and newer) .. ------------------------------------------------------------------------ :arg buffer_origin: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg host_origin: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg region: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg buffer_pitches: :class:`tuple` of :class:`int` of length two or shorter. (optional, "tightly-packed" if unspecified) :arg host_pitches: :class:`tuple` of :class:`int` of length two or shorter. (optional, "tightly-packed" if unspecified) .. ------------------------------------------------------------------------ .. rubric :: Rectangular :class:`Buffer` ↔ :class:`Buffer` transfers (CL 1.1 and newer) .. ------------------------------------------------------------------------ :arg src_origin: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg dst_origin: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg region: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg src_pitches: :class:`tuple` of :class:`int` of length two or shorter. (optional, "tightly-packed" if unspecified) :arg dst_pitches: :class:`tuple` of :class:`int` of length two or shorter. (optional, "tightly-packed" if unspecified) .. ------------------------------------------------------------------------ .. rubric :: Transfer :class:`Image` ↔ host .. ------------------------------------------------------------------------ :arg origin: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg region: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg pitches: :class:`tuple` of :class:`int` of length two or shorter. (optional) .. ------------------------------------------------------------------------ .. rubric :: Transfer :class:`Buffer` ↔ :class:`Image` .. ------------------------------------------------------------------------ :arg offset: offset in buffer (mandatory) :arg origin: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg region: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) .. ------------------------------------------------------------------------ .. rubric :: Transfer :class:`Image` ↔ :class:`Image` .. ------------------------------------------------------------------------ :arg src_origin: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg dest_origin: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) :arg region: :class:`tuple` of :class:`int` of length three or shorter. (mandatory) .. ------------------------------------------------------------------------ .. rubric :: Transfer :class:`SVM`/host ↔ :class:`SVM`/host .. ------------------------------------------------------------------------ :arg byte_count: (optional) If not specified, defaults to the size of the source in versions 2012.x and earlier, and to the minimum of the size of the source and target from 2013.1 on. |std-enqueue-blurb| .. versionadded:: 2011.1 """ if isinstance(dest, MemoryObjectHolder): if dest.type == mem_object_type.BUFFER: if isinstance(src, MemoryObjectHolder): if src.type == mem_object_type.BUFFER: if "src_origin" in kwargs: return _cl._enqueue_copy_buffer_rect( queue, src, dest, **kwargs) else: kwargs["dst_offset"] = kwargs.pop("dest_offset", 0) return _cl._enqueue_copy_buffer(queue, src, dest, **kwargs) elif src.type in [mem_object_type.IMAGE2D, mem_object_type.IMAGE3D]: return _cl._enqueue_copy_image_to_buffer( queue, src, dest, **kwargs) else: raise ValueError("invalid src mem object type") else: # assume from-host if "buffer_origin" in kwargs: return _cl._enqueue_write_buffer_rect(queue, dest, src, **kwargs) else: return _cl._enqueue_write_buffer(queue, dest, src, **kwargs) elif dest.type in [mem_object_type.IMAGE2D, mem_object_type.IMAGE3D]: if isinstance(src, MemoryObjectHolder): if src.type == mem_object_type.BUFFER: return _cl._enqueue_copy_buffer_to_image( queue, src, dest, **kwargs) elif src.type in [mem_object_type.IMAGE2D, mem_object_type.IMAGE3D]: return _cl._enqueue_copy_image(queue, src, dest, **kwargs) else: raise ValueError("invalid src mem object type") else: # assume from-host origin = kwargs.pop("origin") region = kwargs.pop("region") pitches = kwargs.pop("pitches", (0, 0)) if len(pitches) == 1: kwargs["row_pitch"], = pitches else: kwargs["row_pitch"], kwargs["slice_pitch"] = pitches return _cl._enqueue_write_image( queue, dest, origin, region, src, **kwargs) else: raise ValueError("invalid dest mem object type") elif isinstance(dest, SVM): # to SVM if isinstance(src, SVM): src = src.mem return _cl._enqueue_svm_memcpy(queue, dest.mem, src, **kwargs) else: # assume to-host if isinstance(src, MemoryObjectHolder): if src.type == mem_object_type.BUFFER: if "buffer_origin" in kwargs: return _cl._enqueue_read_buffer_rect(queue, src, dest, **kwargs) else: return _cl._enqueue_read_buffer(queue, src, dest, **kwargs) elif src.type in [mem_object_type.IMAGE2D, mem_object_type.IMAGE3D]: origin = kwargs.pop("origin") region = kwargs.pop("region") pitches = kwargs.pop("pitches", (0, 0)) if len(pitches) == 1: kwargs["row_pitch"], = pitches else: kwargs["row_pitch"], kwargs["slice_pitch"] = pitches return _cl._enqueue_read_image( queue, src, origin, region, dest, **kwargs) else: raise ValueError("invalid src mem object type") elif isinstance(src, SVM): # from svm # dest is not a SVM instance, otherwise we'd be in the branch above return _cl._enqueue_svm_memcpy(queue, dest, src.mem, **kwargs) else: # assume from-host raise TypeError("enqueue_copy cannot perform host-to-host transfers")