diff --git a/backends/CMakeLists.txt b/backends/CMakeLists.txt index b812978ed0..e3a8819855 100644 --- a/backends/CMakeLists.txt +++ b/backends/CMakeLists.txt @@ -98,9 +98,11 @@ add_library( SHARED source/dppl_sycl_context_interface.cpp source/dppl_sycl_device_interface.cpp + source/dppl_sycl_kernel_interface.cpp source/dppl_sycl_platform_interface.cpp source/dppl_sycl_queue_interface.cpp source/dppl_sycl_queue_manager.cpp + source/dppl_sycl_usm_interface.cpp source/dppl_utils.cpp ) diff --git a/backends/include/Support/CBindingWrapping.h b/backends/include/Support/CBindingWrapping.h index 40ef4027b2..2a98f59512 100644 --- a/backends/include/Support/CBindingWrapping.h +++ b/backends/include/Support/CBindingWrapping.h @@ -26,11 +26,11 @@ #pragma once #define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ - inline ty *unwrap(ref P) { \ + inline ty *unwrap_##ty(ref P) { \ return reinterpret_cast(P); \ } \ \ - inline ref wrap(const ty *P) { \ + inline ref wrap_##ty(const ty *P) { \ return reinterpret_cast(const_cast(P)); \ } diff --git a/backends/include/dppl_sycl_kernel_interface.h b/backends/include/dppl_sycl_kernel_interface.h new file mode 100644 index 0000000000..0c0ae453c9 --- /dev/null +++ b/backends/include/dppl_sycl_kernel_interface.h @@ -0,0 +1,219 @@ +//===---- dppl_sycl_kernel_interface.h - DPPL-SYCL interface --*--C++ --*--===// +// +// Python Data Parallel Processing Library (PyDPPL) +// +// Copyright 2020 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This header declares a C API to create Sycl kernels from OpenCL kernels. In +/// future, API to create interoperability kernels from other languages such as +/// Level-0 driver API may be added here. +/// +/// \todo Investigate what we should do when we add support for Level-0 API. +/// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "dppl_data_types.h" +#include "dppl_sycl_types.h" +#include "Support/DllExport.h" +#include "Support/ExternC.h" +#include "Support/MemOwnershipAttrs.h" + +DPPL_C_EXTERN_C_BEGIN + +/*! + * @brief Enum of currently support types for kernel arguments. + * + * \todo Add support for sycl::buffer + * + */ +enum DPPLArgTypes +{ + CHAR, + SIGNED_CHAR, + UNSIGNED_CHAR, + SHORT, + INT, + UNSIGNED_INT, + LONG, + UNSIGNED_LONG, + LONG_LONG, + UNSIGNED_LONG_LONG, + SIZE_T, + FLOAT, + DOUBLE, + LONG_DOUBLE, + CHAR_P, + SIGNED_CHAR_P, + UNSIGNED_CHAR_P, + SHORT_P, + INT_P, + UNSIGNED_INT_P, + LONG_P, + UNSIGNED_LONG_P, + LONG_LONG_P, + UNSIGNED_LONG_LONG_P, + SIZE_T_P, + FLOAT_P, + DOUBLE_P, + LONG_DOUBLE_P +}; + +/*! + * @brief A union representing an OpenCL kernel argument that is either a basic + * C type of a pointer of the type. + * + */ +union DPPLArgValue +{ + char char_arg; + signed char schar_arg; + unsigned char uchar_arg; + short short_arg; + int int_arg; + unsigned int uint_arg; + long long_arg; + unsigned long ulong_arg; + long long longlong_arg; + unsigned long long ulonglong_arg; + size_t size_t_arg; + float float_arg; + double double_arg; + long double longdouble_arg; + char *char_p_arg; + signed char *schar_p_arg; + unsigned char *uchar_p_arg; + short *short_p_arg; + int *int_p_arg; + unsigned int *uint_p_arg; + long *long_p_arg; + unsigned long *ulong_p_arg; + long long *longlong_p_arg; + unsigned long long *ulonglong_p_arg; + size_t *size_t_p_arg; + float *float_p_arg; + double *double_p_arg; + long double *longdouble_p_arg; +}; + +/*! + * @brief The tagged union is used to pass through OpenCL kernel arguments to + * Sycl. + * + */ +struct DPPLKernelArg +{ + enum DPPLArgTypes argType; + union DPPLArgValue argVal; +}; + +/*! + * @brief Create a Sycl Kernel from an OpenCL SPIR-V binary + * + * Sycl 1.2 does expose any method to create a sycl::program from a SPIR-V IL + * file. To get around this limitation, we need to use the Sycl feature to + * create an interoperability kernel from an OpenCL kernel. This function first + * creates an OpenCL program and kernel from the SPIR-V binary and then using + * the Sycl-OpenCL interoperability feature creates a Sycl kernel from the + * OpenCL kernel. + * + * The feature to create a Sycl kernel from a SPIR-V IL binary will be available + * in Sycl 2.0. + * + * @param Ctx An opaque pointer to a sycl::context + * @param IL SPIR-V binary + * @return A new SyclProgramRef pointer if the program creation succeeded, + * else returns NULL. + */ +DPPL_API +__dppl_give DPPLSyclKernelRef +DPPLKernel_CreateKernelFromSpirv (__dppl_keep const DPPLSyclContextRef Ctx, + __dppl_keep const void *IL, + size_t length, + const char *KernelName = nullptr); + +/*! + * @brief Returns a C string for the kernel name. + * + * @param KRef DPPLSyclKernelRef pointer to an OpenCL + * interoperability kernel. + * @return If a kernel name exists then returns it as a C string, else + * returns a nullptr. + */ +DPPL_API +__dppl_give const char* +DPPLKernel_GetFunctionName (__dppl_keep const DPPLSyclKernelRef KRef); + +/*! + * @brief Returns the number of arguments for the OpenCL kernel. + * + * @param KRef DPPLSyclKernelRef pointer to an OpenCL + * interoperability kernel. + * @return Returns the number of arguments for the OpenCL interoperability + * kernel. + */ +DPPL_API +size_t +DPPLKernel_GetNumArgs (__dppl_keep const DPPLSyclKernelRef KRef); + +/*! + * @brief Deletes the DPPLSyclKernelRef after casting it to a sycl::kernel. + * + * @param KRef DPPLSyclKernelRef pointer to an OpenCL + * interoperability kernel. + */ +DPPL_API +void +DPPLKernel_DeleteKernelRef (__dppl_take DPPLSyclKernelRef KRef); + + +/*! + * @brief Submits the kernel to the specified queue using give arguments. + * + * A wrapper over sycl::queue.submit(). The function takes an OpenCL + * interoperability kernel, the kernel arguments, and a sycl queue as input + * arguments. The kernel arguments are passed in as an array of the + * DPPLKernelArg tagged union. + * + * \todo sycl::buffer arguments are not supported yet. + * + * @param KRef Opaque pointer to a OpenCL interoperability kernel + * wrapped inside a sycl::kernel. + * @param QRef Opaque pointer to the sycl::queue where the kernel + * will be enqueued. + * @param Args An array of the DPPLKernelArg tagged union type that + * represents the kernel arguments for the kernel. + * @param NArgs The number of kernel arguments (size of Args array). + * @param Range Array storing the range dimensions that can have a + * maximum size of three. Note the number of values + * in the array depends on the number of dimensions. + * @param NDims Number of dimensions in the range (size of Range). + * @return A opaque pointer to the sycl::event returned by the + * sycl::queue.submit() function. + */ +DPPL_API +DPPLSyclEventRef +DPPLKernel_Submit (__dppl_keep DPPLSyclKernelRef KRef, + __dppl_keep DPPLSyclQueueRef QRef, + __dppl_keep DPPLKernelArg *Args, + size_t NArgs, + size_t Range[3], + size_t NDims); + +DPPL_C_EXTERN_C_END diff --git a/backends/include/dppl_sycl_types.h b/backends/include/dppl_sycl_types.h index d1777aae5d..8d3fd2321f 100644 --- a/backends/include/dppl_sycl_types.h +++ b/backends/include/dppl_sycl_types.h @@ -19,39 +19,65 @@ //===----------------------------------------------------------------------===// /// /// \file -/// This file defines types used by DPPL's C interface to SYCL. +/// This file defines opaque pointer types wrapping Sycl object that get used +/// by DPPL's C API. /// //===----------------------------------------------------------------------===// #pragma once /*! - * @brief + * @brief Opaque pointer used to represent references to sycl::context* * + * @see sycl::context */ typedef struct DPPLOpaqueSyclContext *DPPLSyclContextRef; /*! - * @brief + * @brief Opaque pointer used to represent references to sycl::device* * + * @see sycl::device */ typedef struct DPPLOpaqueSyclDevice *DPPLSyclDeviceRef; /*! - * @brief + * @brief Opaque pointer used to represent references to sycl::event* * + * @see sycl::event + */ +typedef struct DPPLOpaqueSyclEvent *DPPLSyclEventRef; + +/*! + * @brief Opaque pointer used to represent references to sycl::kernel* + * + * @see sycl::kernel + */ +typedef struct DPPLOpaqueSyclProgram *DPPLSyclKernelRef; + +/*! + * @brief Opaque pointer used to represent references to sycl::platform* + * + * @see sycl::platform */ typedef struct DPPLOpaqueSyclPlatform *DPPLSyclPlatformRef; +/*! + * @brief Opaque pointer used to represent references to sycl::program* + * + * @see sycl::program + */ +typedef struct DPPLOpaqueSyclProgram *DPPLSyclProgramRef; + /*! - * @brief Used to pass a sycl::queue opaquely through DPPL interfaces. + * @brief Opaque pointer used to represent references to sycl::queue* * * @see sycl::queue */ typedef struct DPPLOpaqueSyclQueue *DPPLSyclQueueRef; /*! - * @brief Used to pass a sycl::program opaquely through DPPL interfaces. + * @brief Used to pass a sycl::usm memory opaquely through DPPL interfaces. * + * @see sycl::usm */ -typedef struct DPPLOpaqueSyclProgram *DPPLSyclProgramRef; +typedef struct DPPLOpaqueSyclUSM *DPPLSyclUSMRef; diff --git a/backends/include/dppl_sycl_usm_interface.h b/backends/include/dppl_sycl_usm_interface.h new file mode 100644 index 0000000000..e85d124c12 --- /dev/null +++ b/backends/include/dppl_sycl_usm_interface.h @@ -0,0 +1,81 @@ +//===--- dppl_sycl_usm_interface.h - DPPL-SYCL interface ---*---C++ -*---===// +// +// Python Data Parallel Processing Library (PyDPPL) +// +// Copyright 2020 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This header declares a C interface to sycl::usm interface functions. +/// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "dppl_data_types.h" +#include "dppl_sycl_types.h" +#include "Support/DllExport.h" +#include "Support/ExternC.h" +#include "Support/MemOwnershipAttrs.h" + +DPPL_C_EXTERN_C_BEGIN + +/*! + * @brief Crete USM shared memory. + * + * @return The pointer to USM shared memory. + */ +DPPL_API +__dppl_give DPPLSyclUSMRef +DPPLmalloc_shared (size_t size, __dppl_keep const DPPLSyclQueueRef QRef); + +/*! + * @brief Crete USM host memory. + * + * @return The pointer to USM host memory. + */ +DPPL_API +__dppl_give DPPLSyclUSMRef +DPPLmalloc_host (size_t size, __dppl_keep const DPPLSyclQueueRef QRef); + +/*! + * @brief Crete USM device memory. + * + * @return The pointer to USM device memory. + */ +DPPL_API +__dppl_give DPPLSyclUSMRef +DPPLmalloc_device (size_t size, __dppl_keep const DPPLSyclQueueRef QRef); + +/*! + * @brief Free USM memory. + * + */ +DPPL_API +void DPPLfree (__dppl_take DPPLSyclUSMRef MRef, + __dppl_keep const DPPLSyclQueueRef QRef); + +/*! + * @brief Get pointer type. + * + * @return "host", "device", "shared" or "unknown" + */ +DPPL_API +const char * +DPPLUSM_GetPointerType (__dppl_keep DPPLSyclUSMRef MRef, + __dppl_keep const DPPLSyclQueueRef QRef); + +DPPL_C_EXTERN_C_END diff --git a/backends/source/dppl_sycl_context_interface.cpp b/backends/source/dppl_sycl_context_interface.cpp index d27b150f74..0a83f16d58 100644 --- a/backends/source/dppl_sycl_context_interface.cpp +++ b/backends/source/dppl_sycl_context_interface.cpp @@ -32,8 +32,8 @@ using namespace cl::sycl; namespace { - // Create wrappers for C Binding types (see CBindingWrapping.h). - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(context, DPPLSyclContextRef) +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(context, DPPLSyclContextRef) } /* end of anonymous namespace */ /*! @@ -44,7 +44,7 @@ namespace */ bool DPPLIsHostContext (__dppl_keep const DPPLSyclContextRef CtxtRef) { - return unwrap(CtxtRef)->is_host(); + return unwrap_context(CtxtRef)->is_host(); } /*! @@ -54,5 +54,5 @@ bool DPPLIsHostContext (__dppl_keep const DPPLSyclContextRef CtxtRef) */ void DPPLDeleteSyclContext (__dppl_take DPPLSyclContextRef CtxtRef) { - delete unwrap(CtxtRef); + delete unwrap_context(CtxtRef); } diff --git a/backends/source/dppl_sycl_device_interface.cpp b/backends/source/dppl_sycl_device_interface.cpp index f70f34be1e..7fa9c8d54f 100644 --- a/backends/source/dppl_sycl_device_interface.cpp +++ b/backends/source/dppl_sycl_device_interface.cpp @@ -35,7 +35,7 @@ using namespace cl::sycl; namespace { // Create wrappers for C Binding types (see CBindingWrapping.h). - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(device, DPPLSyclDeviceRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(device, DPPLSyclDeviceRef) /*! * @brief Helper function to print the metadata for a sycl::device. @@ -68,41 +68,41 @@ void dump_device_info (const device & Device) */ void DPPLDumpDeviceInfo (__dppl_keep const DPPLSyclDeviceRef DRef) { - auto Device = unwrap(DRef); + auto Device = unwrap_device(DRef); dump_device_info(*Device); } void DPPLDeleteSyclDevice (__dppl_take DPPLSyclDeviceRef DRef) { - delete unwrap(DRef); + delete unwrap_device(DRef); } bool DPPLDeviceIsAccelerator (__dppl_keep const DPPLSyclDeviceRef DRef) { - return unwrap(DRef)->is_accelerator(); + return unwrap_device(DRef)->is_accelerator(); } bool DPPLDeviceIsCPU (__dppl_keep const DPPLSyclDeviceRef DRef) { - return unwrap(DRef)->is_cpu(); + return unwrap_device(DRef)->is_cpu(); } bool DPPLDeviceIsGPU (__dppl_keep const DPPLSyclDeviceRef DRef) { - return unwrap(DRef)->is_gpu(); + return unwrap_device(DRef)->is_gpu(); } bool DPPLDeviceIsHost (__dppl_keep const DPPLSyclDeviceRef DRef) { - return unwrap(DRef)->is_host(); + return unwrap_device(DRef)->is_host(); } __dppl_give const char* DPPLGetDeviceName (__dppl_keep const DPPLSyclDeviceRef DRef) { - auto name = unwrap(DRef)->get_info(); + auto name = unwrap_device(DRef)->get_info(); auto cstr_name = new char [name.length()+1]; std::strcpy (cstr_name, name.c_str()); return cstr_name; @@ -111,7 +111,7 @@ DPPLGetDeviceName (__dppl_keep const DPPLSyclDeviceRef DRef) __dppl_give const char* DPPLGetDeviceVendorName (__dppl_keep const DPPLSyclDeviceRef DRef) { - auto vendor = unwrap(DRef)->get_info(); + auto vendor = unwrap_device(DRef)->get_info(); auto cstr_vendor = new char [vendor.length()+1]; std::strcpy (cstr_vendor, vendor.c_str()); return cstr_vendor; @@ -120,7 +120,7 @@ DPPLGetDeviceVendorName (__dppl_keep const DPPLSyclDeviceRef DRef) __dppl_give const char* DPPLGetDeviceDriverInfo (__dppl_keep const DPPLSyclDeviceRef DRef) { - auto driver = unwrap(DRef)->get_info(); + auto driver = unwrap_device(DRef)->get_info(); auto cstr_driver = new char [driver.length()+1]; std::strcpy (cstr_driver, driver.c_str()); return cstr_driver; @@ -128,5 +128,5 @@ DPPLGetDeviceDriverInfo (__dppl_keep const DPPLSyclDeviceRef DRef) bool DPPLGetDeviceHostUnifiedMemory (__dppl_keep const DPPLSyclDeviceRef DRef) { - return unwrap(DRef)->get_info(); + return unwrap_device(DRef)->get_info(); } diff --git a/backends/source/dppl_sycl_kernel_interface.cpp b/backends/source/dppl_sycl_kernel_interface.cpp new file mode 100644 index 0000000000..33f4c45999 --- /dev/null +++ b/backends/source/dppl_sycl_kernel_interface.cpp @@ -0,0 +1,258 @@ +//===--- dppl_sycl_kernel_interface.cpp - DPPL-SYCL interface --*-- C++ -*-===// +// +// Python Data Parallel Processing Library (PyDPPL) +// +// Copyright 2020 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements the functions declared in +/// dppl_sycl_kernel_interface.h. +/// +//===----------------------------------------------------------------------===// + +#include "dppl_sycl_kernel_interface.h" +#include "Support/CBindingWrapping.h" + +#include /* Sycl headers */ +#include /* OpenCL headers */ + +using namespace cl::sycl; + +namespace +{ +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(context, DPPLSyclContextRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(event, DPPLSyclEventRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(kernel, DPPLSyclKernelRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(queue, DPPLSyclQueueRef) + +/*! + * @brief Set the kernel arg object + * + * @param cgh My Param doc + * @param Arg My Param doc + */ +bool set_kernel_arg (handler &cgh, __dppl_keep DPPLKernelArg Arg, size_t idx) +{ + bool arg_set = true; + + switch (Arg.argType) + { + case CHAR: + cgh.set_arg(idx, Arg.argVal.char_arg); + break; + case SIGNED_CHAR: + cgh.set_arg(idx, Arg.argVal.schar_arg); + break; + case UNSIGNED_CHAR: + cgh.set_arg(idx, Arg.argVal.uchar_arg); + break; + case SHORT: + cgh.set_arg(idx, Arg.argVal.short_arg); + break; + case INT: + cgh.set_arg(idx, Arg.argVal.int_arg); + break; + case UNSIGNED_INT: + cgh.set_arg(idx, Arg.argVal.uint_arg); + break; + case LONG: + cgh.set_arg(idx, Arg.argVal.long_arg); + break; + case UNSIGNED_LONG: + cgh.set_arg(idx, Arg.argVal.ulong_arg); + break; + case LONG_LONG: + cgh.set_arg(idx, Arg.argVal.longlong_arg); + break; + case UNSIGNED_LONG_LONG: + cgh.set_arg(idx, Arg.argVal.ulonglong_arg); + break; + case SIZE_T: + cgh.set_arg(idx, Arg.argVal.size_t_arg); + break; + case FLOAT: + cgh.set_arg(idx, Arg.argVal.float_arg); + break; + case DOUBLE: + cgh.set_arg(idx, Arg.argVal.double_arg); + break; + case LONG_DOUBLE: + cgh.set_arg(idx, Arg.argVal.longdouble_arg); + break; + case CHAR_P: + cgh.set_arg(idx, Arg.argVal.char_p_arg); + break; + case SIGNED_CHAR_P: + cgh.set_arg(idx, Arg.argVal.schar_p_arg); + break; + case UNSIGNED_CHAR_P: + cgh.set_arg(idx, Arg.argVal.uchar_p_arg); + break; + case SHORT_P: + cgh.set_arg(idx, Arg.argVal.short_p_arg); + break; + case INT_P: + cgh.set_arg(idx, Arg.argVal.int_p_arg); + break; + case UNSIGNED_INT_P: + cgh.set_arg(idx, Arg.argVal.uint_p_arg); + break; + case LONG_P: + cgh.set_arg(idx, Arg.argVal.long_p_arg); + break; + case UNSIGNED_LONG_P: + cgh.set_arg(idx, Arg.argVal.ulong_p_arg); + break; + case LONG_LONG_P: + cgh.set_arg(idx, Arg.argVal.longlong_p_arg); + break; + case UNSIGNED_LONG_LONG_P: + cgh.set_arg(idx, Arg.argVal.ulonglong_p_arg); + break; + case SIZE_T_P: + cgh.set_arg(idx, Arg.argVal.size_t_p_arg); + break; + case FLOAT_P: + cgh.set_arg(idx, Arg.argVal.float_p_arg); + break; + case DOUBLE_P: + cgh.set_arg(idx, Arg.argVal.double_p_arg); + break; + case LONG_DOUBLE_P: + cgh.set_arg(idx, Arg.argVal.longdouble_p_arg); + break; + default: + // \todo handle errors + arg_set = false; + std::cerr << "Kernel argument could not be created.\n"; + break; + } + return arg_set; +} + +} /* end of anonymous namespace */ + +__dppl_give DPPLSyclKernelRef +DPPLKernel_CreateKernelFromSpirv (__dppl_keep const DPPLSyclContextRef Ctx, + __dppl_keep const void *IL, + size_t length, + const char *KernelName) +{ + cl_int err; + + auto SyclCtx = unwrap_context(Ctx); + auto CLCtx = SyclCtx->get(); + auto CLProgram = clCreateProgramWithIL(CLCtx, IL, length, &err); + if (err) { + // \todo: record the error string and any other information. + return nullptr; + } + auto SyclDevices = SyclCtx->get_devices(); + + // Get a list of CL Devices from the Sycl devices + auto CLDevices = new cl_device_id[SyclDevices.size()]; + for (auto i = 0ul; i < SyclDevices.size(); ++i) + CLDevices[i] = SyclDevices[i].get(); + + // Create the OpenCL interoperability program + err = clBuildProgram(CLProgram, (cl_uint)(SyclDevices.size()), CLDevices, + nullptr, nullptr, nullptr); + // free the CLDevices array + delete[] CLDevices; + + if (err) { + // \todo: record the error string and any other information. + return nullptr; + } + + // Create the OpenCL interoperability kernel + auto CLKernel = clCreateKernel(CLProgram, KernelName, &err); + if (err) { + // \todo: record the error string and any other information. + return nullptr; + } + auto SyclKernel = new kernel(CLKernel, *SyclCtx); + return wrap_kernel(SyclKernel); +} + +__dppl_give const char* +DPPLKernel_GetFunctionName (__dppl_keep const DPPLSyclKernelRef Kernel) +{ + auto SyclKernel = unwrap_kernel(Kernel); + auto kernel_name = SyclKernel->get_info(); + if(kernel_name.empty()) + return nullptr; + auto cstr_name = new char [kernel_name.length()+1]; + std::strcpy (cstr_name, kernel_name.c_str()); + return cstr_name; +} + +size_t +DPPLKernel_GetNumArgs (__dppl_keep const DPPLSyclKernelRef Kernel) +{ + auto SyclKernel = unwrap_kernel(Kernel); + auto num_args = SyclKernel->get_info(); + return (size_t)num_args; +} + +void +DPPLKernel_DeleteKernelRef (__dppl_take DPPLSyclKernelRef Kernel) +{ + delete unwrap_kernel(Kernel); +} + + +DPPL_API +DPPLSyclEventRef +DPPLKernel_Submit (__dppl_keep DPPLSyclKernelRef KRef, + __dppl_keep DPPLSyclQueueRef QRef, + __dppl_keep DPPLKernelArg *Args, + size_t NArgs, + size_t Range[3], + size_t NDims) +{ + auto Kernel = unwrap_kernel(KRef); + auto Queue = unwrap_queue(QRef); + event e; + + e = Queue->submit([&](handler& cgh) { + for (auto i = 0ul; i < 4; ++i) { + // \todo add support for Sycl buffers + // \todo handle errors properly + if(!set_kernel_arg(cgh, Args[i], i)) + exit(1); + } + switch(NDims) + { + case 1: + cgh.parallel_for(range<1>{Range[0]}, *Kernel); + break; + case 2: + cgh.parallel_for(range<2>{Range[0], Range[1]}, *Kernel); + break; + case 3: + cgh.parallel_for(range<3>{Range[0], Range[1], Range[2]}, *Kernel); + break; + default: + // \todo handle the error + std::cerr << "Range cannot be greater than three dimensions.\n"; + exit(1); + } + }); + + return wrap_event(new event(e)); +} diff --git a/backends/source/dppl_sycl_queue_interface.cpp b/backends/source/dppl_sycl_queue_interface.cpp index e02479d69d..efb23554d5 100644 --- a/backends/source/dppl_sycl_queue_interface.cpp +++ b/backends/source/dppl_sycl_queue_interface.cpp @@ -34,24 +34,25 @@ using namespace cl::sycl; namespace { // Create wrappers for C Binding types (see CBindingWrapping.h). - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(queue, DPPLSyclQueueRef) - +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(queue, DPPLSyclQueueRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(device, DPPLSyclDeviceRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(context, DPPLSyclContextRef) } /* end of anonymous namespace */ __dppl_give DPPLSyclDeviceRef DPPLGetDeviceFromQueue (__dppl_keep const DPPLSyclQueueRef QRef) { - auto Q = unwrap(QRef); + auto Q = unwrap_queue(QRef); auto Device = new device(Q->get_device()); - return reinterpret_cast(Device); + return wrap_device(Device); } __dppl_give DPPLSyclContextRef DPPLGetContextFromQueue (__dppl_keep const DPPLSyclQueueRef QRef) { - auto Q = unwrap(QRef); + auto Q = unwrap_queue(QRef); auto Context = new context(Q->get_context()); - return reinterpret_cast(Context); + return wrap_context(Context); } /*! @@ -59,5 +60,5 @@ DPPLGetContextFromQueue (__dppl_keep const DPPLSyclQueueRef QRef) */ void DPPLDeleteSyclQueue (__dppl_take DPPLSyclQueueRef QRef) { - delete unwrap(QRef); + delete unwrap_queue(QRef); } diff --git a/backends/source/dppl_sycl_queue_manager.cpp b/backends/source/dppl_sycl_queue_manager.cpp index 17776fda11..c299269e5d 100644 --- a/backends/source/dppl_sycl_queue_manager.cpp +++ b/backends/source/dppl_sycl_queue_manager.cpp @@ -39,8 +39,8 @@ using namespace cl::sycl; namespace { - // Create wrappers for C Binding types (see CBindingWrapping.h). - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(queue, DPPLSyclQueueRef) +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(queue, DPPLSyclQueueRef) void error_reporter (const std::string & msg) { @@ -128,7 +128,7 @@ DPPLSyclQueueRef QMgrHelper::getCurrentQueue () if(active_queues.empty()) error_reporter("No currently active queues."); auto last = QMgrHelper::active_queues.size() - 1; - return wrap(new queue(QMgrHelper::active_queues[last])); + return wrap_queue(new queue(QMgrHelper::active_queues[last])); } /*! @@ -169,7 +169,7 @@ QMgrHelper::getQueue (DPPLSyclDeviceType DeviceTy, error_reporter("Unsupported device type."); } - return wrap(QRef); + return wrap_queue(QRef); } /*! @@ -254,7 +254,7 @@ QMgrHelper::pushSyclQueue (DPPLSyclDeviceType DeviceTy, size_t DNum) } } - return wrap(QRef); + return wrap_queue(QRef); } /*! diff --git a/backends/source/dppl_sycl_usm_interface.cpp b/backends/source/dppl_sycl_usm_interface.cpp new file mode 100644 index 0000000000..eaebbca107 --- /dev/null +++ b/backends/source/dppl_sycl_usm_interface.cpp @@ -0,0 +1,92 @@ +//===--- dppl_sycl_usm_interface.cpp - DPPL-SYCL interface --*- C++ -*---===// +// +// Python Data Parallel Processing Library (PyDPPL) +// +// Copyright 2020 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements the data types and functions declared in +/// dppl_sycl_usm_interface.h. +/// +//===----------------------------------------------------------------------===// + +#include "dppl_sycl_usm_interface.h" +#include "Support/CBindingWrapping.h" + +#include /* SYCL headers */ + +using namespace cl::sycl; + +namespace +{ +// Create wrappers for C Binding types (see CBindingWrapping.h). + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(queue, DPPLSyclQueueRef) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(void, DPPLSyclUSMRef) + +} /* end of anonymous namespace */ + +__dppl_give DPPLSyclUSMRef +DPPLmalloc_shared (size_t size, __dppl_keep const DPPLSyclQueueRef QRef) +{ + auto Q = unwrap(QRef); + auto Ptr = malloc_shared(size, *Q); + return reinterpret_cast(Ptr); +} + +__dppl_give DPPLSyclUSMRef +DPPLmalloc_host (size_t size, __dppl_keep const DPPLSyclQueueRef QRef) +{ + auto Q = unwrap(QRef); + auto Ptr = malloc_host(size, *Q); + return reinterpret_cast(Ptr); +} + +__dppl_give DPPLSyclUSMRef +DPPLmalloc_device (size_t size, __dppl_keep const DPPLSyclQueueRef QRef) +{ + auto Q = unwrap(QRef); + auto Ptr = malloc_device(size, *Q); + return reinterpret_cast(Ptr); +} + +void DPPLfree (__dppl_take DPPLSyclUSMRef MRef, + __dppl_keep const DPPLSyclQueueRef QRef) +{ + auto Ptr = unwrap(MRef); + auto Q = unwrap(QRef); + free(Ptr, *Q); +} + +const char * +DPPLUSM_GetPointerType (__dppl_keep DPPLSyclUSMRef MRef, + __dppl_keep const DPPLSyclQueueRef QRef) +{ + auto Ptr = unwrap(MRef); + auto Q = unwrap(QRef); + + auto kind = get_pointer_type(Ptr, Q->get_context()); + switch(kind) { + case usm::alloc::host: + return "host"; + case usm::alloc::device: + return "device"; + case usm::alloc::shared: + return "shared"; + default: + return "unknown"; + } +} diff --git a/backends/tests/CMakeLists.txt b/backends/tests/CMakeLists.txt index c3add176ba..75bce82ac5 100644 --- a/backends/tests/CMakeLists.txt +++ b/backends/tests/CMakeLists.txt @@ -3,9 +3,9 @@ string(COMPARE EQUAL "${GTEST_LIB_DIR}" "" no_gtest_lib_dir) if(${no_gtest_incl_dir} OR ${no_gtest_lib_dir}) message(WARNING - "GTest is needed to test PyDPPL's backend test cases. Pass in \ - -DGTEST_INCLUDE_DIR and -DGTEST_LIB_DIR when you configure Cmake if\ - you wish to run PyDPPL backend tests." + "GTest is needed to test PyDPPL's backend test cases. Pass in \ + -DGTEST_INCLUDE_DIR and -DGTEST_LIB_DIR when you configure Cmake \ + if you wish to run PyDPPL backend tests." ) else() # We need thread support for gtest @@ -21,6 +21,7 @@ else() include_directories(../include) link_directories(${GTEST_LIB_DIR}) + link_directories(${CMAKE_BINARY_DIR}) set(PYDPPL_BACKEND_TEST_CASES test_sycl_queue_manager diff --git a/dppl/_memory.pyx b/dppl/_memory.pyx new file mode 100644 index 0000000000..c20e211ed3 --- /dev/null +++ b/dppl/_memory.pyx @@ -0,0 +1,107 @@ +import dppl +from dppl.backend cimport * +from ._sycl_core cimport SyclContext, SyclQueue + +from cpython cimport Py_buffer + + +cdef class Memory: + cdef DPPLSyclUSMRef memory_ptr + cdef Py_ssize_t nbytes + cdef SyclQueue queue + + cdef _cinit(self, Py_ssize_t nbytes, ptr_type): + cdef SyclQueue q + cdef DPPLSyclUSMRef p + + self.memory_ptr = NULL + self.queue = None + self.nbytes = 0 + + if (nbytes > 0): + q = dppl.get_current_queue() + + if (ptr_type == "shared"): + p = DPPLmalloc_shared(nbytes, q.get_queue_ref()) + elif (ptr_type == "host"): + p = DPPLmalloc_host(nbytes, q.get_queue_ref()) + elif (ptr_type == "device"): + p = DPPLmalloc_device(nbytes, q.get_queue_ref()) + else: + raise RuntimeError("Pointer type is unknown: {}" \ + .format(ptr_type)) + + if (p): + self.memory_ptr = p + self.nbytes = nbytes + self.queue = q + else: + raise RuntimeError("Null memory pointer returned") + else: + raise ValueError("Non-positive number of bytes found.") + + def __dealloc__(self): + if (self.memory_ptr): + DPPLfree(self.memory_ptr, self.queue.get_queue_ref()) + self.memory_ptr = NULL + self.nbytes = 0 + self.queue = None + + cdef _getbuffer(self, Py_buffer *buffer, int flags): + buffer.buf = self.memory_ptr + buffer.format = 'B' # byte + buffer.internal = NULL # see References + buffer.itemsize = 1 + buffer.len = self.nbytes + buffer.ndim = 1 + buffer.obj = self + buffer.readonly = 0 + buffer.shape = &self.nbytes + buffer.strides = &buffer.itemsize + buffer.suboffsets = NULL # for pointer arrays only + + property pointer: + def __get__(self): + return (self.memory_ptr) + + property nbytes: + def __get__(self): + return self.nbytes + + property _queue: + def __get__(self): + return self.queue + + def __repr__(self): + return "" \ + .format(self.nbytes, hex((self.memory_ptr))) + + def _usm_type(self): + cdef const char* kind + kind = DPPLUSM_GetPointerType(self.memory_ptr, + self.queue.get_queue_ref()) + return kind.decode('UTF-8') + + +cdef class MemoryUSMShared(Memory): + + def __cinit__(self, Py_ssize_t nbytes): + self._cinit(nbytes, "shared") + + def __getbuffer__(self, Py_buffer *buffer, int flags): + self._getbuffer(buffer, flags) + + +cdef class MemoryUSMHost(Memory): + + def __cinit__(self, Py_ssize_t nbytes): + self._cinit(nbytes, "host") + + def __getbuffer__(self, Py_buffer *buffer, int flags): + self._getbuffer(buffer, flags) + + +cdef class MemoryUSMDevice(Memory): + + def __cinit__(self, Py_ssize_t nbytes): + self._cinit(nbytes, "device") diff --git a/dppl/_sycl_core.pxd b/dppl/_sycl_core.pxd new file mode 100644 index 0000000000..c4b8dd2ab1 --- /dev/null +++ b/dppl/_sycl_core.pxd @@ -0,0 +1,61 @@ +##===------------- sycl_core.pxd - DPPL interface ------*- Cython -*-------===## +## +## Python Data Parallel Processing Library (PyDPPL) +## +## Copyright 2020 Intel Corporation +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## +##===----------------------------------------------------------------------===## +## +## \file +## This file defines the Cython interface for the Sycl API of PyDPPL. +## +##===----------------------------------------------------------------------===## + +from .backend cimport * + + +cdef class SyclContext: + ''' Wrapper class for a Sycl Context + ''' + cdef DPPLSyclContextRef ctxt_ptr + + @staticmethod + cdef SyclContext _create (DPPLSyclContextRef ctxt) + cdef DPPLSyclContextRef get_context_ref (self) + + +cdef class SyclDevice: + ''' Wrapper class for a Sycl Device + ''' + cdef DPPLSyclDeviceRef device_ptr + cdef const char *vendor_name + cdef const char *device_name + cdef const char *driver_version + + @staticmethod + cdef SyclDevice _create (DPPLSyclDeviceRef dref) + cdef DPPLSyclDeviceRef get_device_ptr (self) + + +cdef class SyclQueue: + ''' Wrapper class for a Sycl queue. + ''' + cdef DPPLSyclQueueRef queue_ptr + + @staticmethod + cdef SyclQueue _create (DPPLSyclQueueRef qref) + cpdef SyclContext get_sycl_context (self) + cpdef SyclDevice get_sycl_device (self) + cdef DPPLSyclQueueRef get_queue_ref (self) diff --git a/dppl/backend.pxd b/dppl/backend.pxd new file mode 100644 index 0000000000..d19cf02e2a --- /dev/null +++ b/dppl/backend.pxd @@ -0,0 +1,106 @@ +##===------------- backend.pyx - DPPL interface ------*- Cython -*-------===## +## +## Python Data Parallel Processing Library (PyDPPL) +## +## Copyright 2020 Intel Corporation +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## +##===----------------------------------------------------------------------===## +## +## \file +## This file defines the Cython interface for the backend API of PyDPPL. +## +##===----------------------------------------------------------------------===## + +from libcpp cimport bool + + +cdef extern from "dppl_utils.h": + cdef void DPPLDeleteCString (const char *str) + + +cdef extern from "dppl_sycl_types.h": + cdef struct DPPLOpaqueSyclContext + cdef struct DPPLOpaqueSyclQueue + cdef struct DPPLOpaqueSyclDevice + cdef struct DPPLOpaqueSyclUSM + + ctypedef DPPLOpaqueSyclContext* DPPLSyclContextRef + ctypedef DPPLOpaqueSyclQueue* DPPLSyclQueueRef + ctypedef DPPLOpaqueSyclDevice* DPPLSyclDeviceRef + ctypedef DPPLOpaqueSyclUSM* DPPLSyclUSMRef + + +cdef extern from "dppl_sycl_context_interface.h": + cdef void DPPLDeleteSyclContext (DPPLSyclContextRef CtxtRef) except + + + +cdef extern from "dppl_sycl_device_interface.h": + cdef void DPPLDumpDeviceInfo (const DPPLSyclDeviceRef DRef) except + + cdef void DPPLDeleteSyclDevice (DPPLSyclDeviceRef DRef) except + + cdef void DPPLDumpDeviceInfo (const DPPLSyclDeviceRef DRef) except + + cdef bool DPPLDeviceIsAccelerator (const DPPLSyclDeviceRef DRef) except + + cdef bool DPPLDeviceIsCPU (const DPPLSyclDeviceRef DRef) except + + cdef bool DPPLDeviceIsGPU (const DPPLSyclDeviceRef DRef) except + + cdef bool DPPLDeviceIsHost (const DPPLSyclDeviceRef DRef) except + + cdef const char* DPPLGetDeviceDriverInfo (const DPPLSyclDeviceRef DRef) \ + except + + cdef const char* DPPLGetDeviceName (const DPPLSyclDeviceRef DRef) except + + cdef const char* DPPLGetDeviceVendorName (const DPPLSyclDeviceRef DRef) \ + except + + cdef bool DPPLGetDeviceHostUnifiedMemory (const DPPLSyclDeviceRef DRef) \ + except + + + +cdef extern from "dppl_sycl_platform_interface.h": + cdef size_t DPPLPlatform_GetNumPlatforms () + cdef void DPPLPlatform_DumpInfo () + + +cdef extern from "dppl_sycl_queue_interface.h": + cdef void DPPLDeleteSyclQueue (DPPLSyclQueueRef QRef) except + + cdef DPPLSyclContextRef DPPLGetContextFromQueue (const DPPLSyclQueueRef Q) \ + except+ + cdef DPPLSyclDeviceRef DPPLGetDeviceFromQueue (const DPPLSyclQueueRef Q) \ + except + + + +cdef extern from "dppl_sycl_queue_manager.h": + cdef enum _device_type 'DPPLSyclDeviceType': + _GPU 'DPPL_GPU' + _CPU 'DPPL_CPU' + + cdef DPPLSyclQueueRef DPPLGetCurrentQueue () except + + cdef size_t DPPLGetNumCPUQueues () except + + cdef size_t DPPLGetNumGPUQueues () except + + cdef size_t DPPLGetNumActivatedQueues () except + + cdef DPPLSyclQueueRef DPPLGetQueue (_device_type DTy, + size_t device_num) except + + cdef void DPPLPopSyclQueue () except + + cdef DPPLSyclQueueRef DPPLPushSyclQueue (_device_type DTy, + size_t device_num) except + + cdef void DPPLSetAsDefaultQueue (_device_type DTy, + size_t device_num) except + + + +cdef extern from "dppl_sycl_usm_interface.h": + cdef DPPLSyclUSMRef DPPLmalloc_shared (size_t size, DPPLSyclQueueRef QRef) \ + except + + cdef DPPLSyclUSMRef DPPLmalloc_host (size_t size, DPPLSyclQueueRef QRef) \ + except + + cdef DPPLSyclUSMRef DPPLmalloc_device (size_t size, DPPLSyclQueueRef QRef) \ + except + + cdef void DPPLfree (DPPLSyclUSMRef MRef, DPPLSyclQueueRef QRef) except + + cdef const char* DPPLUSM_GetPointerType (DPPLSyclUSMRef MRef, + DPPLSyclQueueRef QRef) except + diff --git a/dppl/sycl_core.pyx b/dppl/sycl_core.pyx index 1ed47334df..5df3af4367 100644 --- a/dppl/sycl_core.pyx +++ b/dppl/sycl_core.pyx @@ -29,10 +29,12 @@ from __future__ import print_function from enum import Enum, auto import logging -from libcpp cimport bool +from dppl.backend cimport * + _logger = logging.getLogger(__name__) + class device_type(Enum): gpu = auto() cpu = auto() @@ -44,71 +46,8 @@ cdef class UnsupportedDeviceTypeError(Exception): ''' pass -cdef extern from "dppl_utils.h": - cdef void DPPLDeleteCString (const char *str) - -cdef extern from "dppl_sycl_types.h": - cdef struct DPPLOpaqueSyclContext: - pass - cdef struct DPPLOpaqueSyclQueue: - pass - cdef struct DPPLOpaqueSyclDevice: - pass - - ctypedef DPPLOpaqueSyclContext* DPPLSyclContextRef - ctypedef DPPLOpaqueSyclQueue* DPPLSyclQueueRef - ctypedef DPPLOpaqueSyclDevice* DPPLSyclDeviceRef - -cdef extern from "dppl_sycl_context_interface.h": - cdef void DPPLDeleteSyclContext (DPPLSyclContextRef CtxtRef) except + - -cdef extern from "dppl_sycl_device_interface.h": - cdef void DPPLDumpDeviceInfo (const DPPLSyclDeviceRef DRef) except + - cdef void DPPLDeleteSyclDevice (DPPLSyclDeviceRef DRef) except + - cdef void DPPLDumpDeviceInfo (const DPPLSyclDeviceRef DRef) except + - cdef bool DPPLDeviceIsAccelerator (const DPPLSyclDeviceRef DRef) except + - cdef bool DPPLDeviceIsCPU (const DPPLSyclDeviceRef DRef) except + - cdef bool DPPLDeviceIsGPU (const DPPLSyclDeviceRef DRef) except + - cdef bool DPPLDeviceIsHost (const DPPLSyclDeviceRef DRef) except + - cdef const char* DPPLGetDeviceDriverInfo (const DPPLSyclDeviceRef DRef) \ - except + - cdef const char* DPPLGetDeviceName (const DPPLSyclDeviceRef DRef) except + - cdef const char* DPPLGetDeviceVendorName (const DPPLSyclDeviceRef DRef) \ - except + - cdef bool DPPLGetDeviceHostUnifiedMemory (const DPPLSyclDeviceRef DRef) \ - except + - -cdef extern from "dppl_sycl_platform_interface.h": - cdef size_t DPPLPlatform_GetNumPlatforms () - cdef void DPPLPlatform_DumpInfo () - -cdef extern from "dppl_sycl_queue_interface.h": - cdef void DPPLDeleteSyclQueue (DPPLSyclQueueRef QRef) except + - cdef DPPLSyclContextRef DPPLGetContextFromQueue (const DPPLSyclQueueRef Q) \ - except+ - cdef DPPLSyclDeviceRef DPPLGetDeviceFromQueue (const DPPLSyclQueueRef Q) \ - except + - -cdef extern from "dppl_sycl_queue_manager.h": - cdef enum _device_type 'DPPLSyclDeviceType': - _GPU 'DPPL_GPU' - _CPU 'DPPL_CPU' - - cdef DPPLSyclQueueRef DPPLGetCurrentQueue () except + - cdef size_t DPPLGetNumCPUQueues () except + - cdef size_t DPPLGetNumGPUQueues () except + - cdef size_t DPPLGetNumActivatedQueues () except + - cdef DPPLSyclQueueRef DPPLGetQueue (_device_type DTy, - size_t device_num) except + - cdef void DPPLPopSyclQueue () except + - cdef DPPLSyclQueueRef DPPLPushSyclQueue (_device_type DTy, - size_t device_num) except + - cdef void DPPLSetAsDefaultQueue (_device_type DTy, - size_t device_num) except + - cdef class SyclContext: - cdef DPPLSyclContextRef ctxt_ptr @staticmethod cdef SyclContext _create (DPPLSyclContextRef ctxt): @@ -126,10 +65,6 @@ cdef class SyclContext: cdef class SyclDevice: ''' Wrapper class for a Sycl Device ''' - cdef DPPLSyclDeviceRef device_ptr - cdef const char *vendor_name - cdef const char *device_name - cdef const char *driver_version @staticmethod cdef SyclDevice _create (DPPLSyclDeviceRef dref): @@ -178,7 +113,6 @@ cdef class SyclDevice: cdef class SyclQueue: ''' Wrapper class for a Sycl queue. ''' - cdef DPPLSyclQueueRef queue_ptr @staticmethod cdef SyclQueue _create (DPPLSyclQueueRef qref): @@ -189,10 +123,10 @@ cdef class SyclQueue: def __dealloc__ (self): DPPLDeleteSyclQueue(self.queue_ptr) - cpdef get_sycl_context (self): + cpdef SyclContext get_sycl_context (self): return SyclContext._create(DPPLGetContextFromQueue(self.queue_ptr)) - cpdef get_sycl_device (self): + cpdef SyclDevice get_sycl_device (self): return SyclDevice._create(DPPLGetDeviceFromQueue(self.queue_ptr)) cdef DPPLSyclQueueRef get_queue_ref (self): diff --git a/dppl/tests/__init__.py b/dppl/tests/__init__.py index b7d39c5dfd..6bd91b208f 100644 --- a/dppl/tests/__init__.py +++ b/dppl/tests/__init__.py @@ -1 +1,2 @@ from .test_dump_functions import * +from .dppl_tests import * diff --git a/dppl/tests/dppl_tests/__init__.py b/dppl/tests/dppl_tests/__init__.py index adcaad3954..7017278251 100644 --- a/dppl/tests/dppl_tests/__init__.py +++ b/dppl/tests/dppl_tests/__init__.py @@ -1 +1,2 @@ -from .test_sycl_queue_manager import * \ No newline at end of file +from .test_sycl_queue_manager import * +from .test_sycl_memory_manager import * diff --git a/dppl/tests/dppl_tests/test_sycl_memory_manager.py b/dppl/tests/dppl_tests/test_sycl_memory_manager.py new file mode 100644 index 0000000000..fc6cf16aea --- /dev/null +++ b/dppl/tests/dppl_tests/test_sycl_memory_manager.py @@ -0,0 +1,83 @@ +##===---------- test_sycl_queue_manager.py - dppl -------*- Python -*-----===## +## +## Python Data Parallel Processing Library (PyDPPL) +## +## Copyright 2020 Intel Corporation +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## +##===----------------------------------------------------------------------===## + +import unittest +import dppl +from dppl._memory import MemoryUSMShared, MemoryUSMHost, MemoryUSMDevice + + +class TestMemory (unittest.TestCase): + + def test_memory_create (self): + nbytes = 1024 + mobj = MemoryUSMShared(nbytes) + self.assertEqual(mobj.nbytes, nbytes) + + def _create_memory (self): + nbytes = 1024 + mobj = MemoryUSMShared(nbytes) + return mobj + + def test_memory_without_context (self): + mobj = self._create_memory() + + # Without context + self.assertEqual(mobj._usm_type(), 'shared') + + def test_memory_cpu_context (self): + mobj = self._create_memory() + + # CPU context + with dppl.device_context(dppl.device_type.cpu): + self.assertEqual(mobj._usm_type(), 'shared') + + def test_memory_gpu_context (self): + mobj = self._create_memory() + + # GPU context + with dppl.device_context(dppl.device_type.gpu): + self.assertEqual(mobj._usm_type(), 'shared') + + +class TestMemoryUSMShared(unittest.TestCase): + """Tests for MemoryUSMShared + """ + + def test_create (self): + m = MemoryUSMShared(1024) + self.assertEqual(m._usm_type(), 'shared') + + +class TestMemoryUSMHost(unittest.TestCase): + """Tests for MemoryUSMHost + """ + + def test_create (self): + m = MemoryUSMHost(1024) + self.assertEqual(m._usm_type(), 'host') + + +class TestMemoryUSMDevice(unittest.TestCase): + """Tests for MemoryUSMDevice + """ + + def test_create (self): + m = MemoryUSMDevice(1024) + self.assertEqual(m._usm_type(), 'device') diff --git a/setup.py b/setup.py index a7c209ee3c..2a90338032 100644 --- a/setup.py +++ b/setup.py @@ -25,8 +25,8 @@ import sys import versioneer -from Cython.Build import cythonize from setuptools import setup, Extension, find_packages +from Cython.Build import cythonize import numpy as np @@ -78,7 +78,7 @@ def get_other_cxxflags(): # what compiler we are using. return ['/Ox', '/std:c++17'] -def getpyexts(): +def extensions(): # Security flags eca = get_sdl_cflags() ela = get_sdl_ldflags() @@ -104,17 +104,22 @@ def getpyexts(): elif IS_WIN: runtime_library_dirs = [] - exts = cythonize(Extension('dppl._sycl_core', - [os.path.abspath('dppl/sycl_core.pyx'),], - depends=[dppl_sycl_interface_include,], - include_dirs=[np.get_include(), - dppl_sycl_interface_include], - extra_compile_args=eca + get_other_cxxflags(), - extra_link_args=ela, - libraries=libs, - library_dirs=librarys, - runtime_library_dirs=runtime_library_dirs, - language='c++')) + extension_args = { + "depends": [dppl_sycl_interface_include,], + "include_dirs": [np.get_include(), dppl_sycl_interface_include], + "extra_compile_args": eca + get_other_cxxflags(), + "extra_link_args": ela, "libraries": libs, "library_dirs": librarys, + "runtime_library_dirs": runtime_library_dirs, "language": 'c++', + } + + extensions = [ + Extension('dppl._sycl_core', [os.path.abspath('dppl/sycl_core.pyx'),], + **extension_args), + Extension('dppl._memory', [os.path.abspath('dppl/_memory.pyx'),], + **extension_args), + ] + + exts = cythonize(extensions) return exts setup( @@ -126,7 +131,7 @@ def getpyexts(): author="Intel Corporation", url='https://github.com/IntelPython/PyDPPL', packages=find_packages(include=["dppl", "dppl.*"]), - ext_modules = getpyexts(), + ext_modules = extensions(), setup_requires=requirements, cffi_modules=[ "./dppl/opencl_core.py:ffi"