From 25fbfd011e283c07b77e89751a5de2cd155a2999 Mon Sep 17 00:00:00 2001 From: Chaluvadi Date: Wed, 13 Mar 2024 10:35:41 -0400 Subject: [PATCH 1/9] utility functions for tests --- tests/utility_functions.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/utility_functions.py diff --git a/tests/utility_functions.py b/tests/utility_functions.py new file mode 100644 index 0000000..3e45f78 --- /dev/null +++ b/tests/utility_functions.py @@ -0,0 +1,13 @@ +import pytest + +import arrayfire_wrapper.lib as wrapper +from arrayfire_wrapper.dtypes import Dtype, c64, f16, f64 + + +def check_type_supported(dtype: Dtype) -> None: + """Checks to see if the specified type is supported by the current system""" + if dtype in [f64, c64] and not wrapper.get_dbl_support(): + pytest.skip("Device does not support double types") + + if dtype == f16 and not wrapper.get_half_support(): + pytest.skip("Device does not support half types.") From 2fbaace5e3775703e0c97471017cd0bba5df1a77 Mon Sep 17 00:00:00 2001 From: Chaluvadi Date: Tue, 5 Mar 2024 09:50:46 -0500 Subject: [PATCH 2/9] added unit tests for range function --- tests/test_range.py | 61 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tests/test_range.py diff --git a/tests/test_range.py b/tests/test_range.py new file mode 100644 index 0000000..1571698 --- /dev/null +++ b/tests/test_range.py @@ -0,0 +1,61 @@ +import random + +import pytest + +import arrayfire_wrapper.dtypes as dtypes +import arrayfire_wrapper.lib as wrapper + + +@pytest.mark.parametrize( + "shape", + [ + (), + (random.randint(1, 10), 1), + (random.randint(1, 10), random.randint(1, 10)), + (random.randint(1, 10), random.randint(1, 10), random.randint(1, 10)), + (random.randint(1, 10), random.randint(1, 10), random.randint(1, 10), random.randint(1, 10)), + ], +) +def test_range_shape(shape: tuple) -> None: + """Test if the range function output an AFArray with the correct shape""" + dim = 2 + dtype = dtypes.s16 + + result = wrapper.range(shape, dim, dtype) + + assert wrapper.get_dims(result)[0 : len(shape)] == shape # noqa: E203 + + +def test_range_invalid_shape() -> None: + """Test if range function correctly handles an invalid shape""" + with pytest.raises(TypeError): + shape = ( + random.randint(1, 10), + random.randint(1, 10), + random.randint(1, 10), + random.randint(1, 10), + random.randint(1, 10), + ) + dim = 2 + dtype = dtypes.s16 + + wrapper.range(shape, dim, dtype) + + +@pytest.mark.parametrize( + "shape", + [ + (), + (random.randint(1, 10), 1), + (random.randint(1, 10), random.randint(1, 10)), + (random.randint(1, 10), random.randint(1, 10), random.randint(1, 10)), + (random.randint(1, 10), random.randint(1, 10), random.randint(1, 10), random.randint(1, 10)), + ], +) +def test_range_invalid_dim(shape: tuple) -> None: + """Test if the range function can properly handle and invalid dimension given""" + with pytest.raises(RuntimeError): + dim = random.randint(4, 10) + dtype = dtypes.s16 + + wrapper.range(shape, dim, dtype) From 1bc0f3a84cf3733040a0a0f6a2bc6ce790dc933e Mon Sep 17 00:00:00 2001 From: Chaluvadi Date: Tue, 12 Mar 2024 10:48:35 -0400 Subject: [PATCH 3/9] Readability changes to cosntants tests --- tests/test_constants.py | 69 +++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/tests/test_constants.py b/tests/test_constants.py index 855d94a..929c8ed 100644 --- a/tests/test_constants.py +++ b/tests/test_constants.py @@ -2,8 +2,23 @@ import pytest -import arrayfire_wrapper.dtypes as dtypes import arrayfire_wrapper.lib as wrapper +from arrayfire_wrapper.dtypes import ( + Dtype, + c32, + c64, + c_api_value_to_dtype, + f16, + f32, + f64, + s16, + s32, + s64, + u8, + u16, + u32, + u64, +) invalid_shape = ( random.randint(1, 10), @@ -14,6 +29,9 @@ ) +types = [s16, s32, s64, u8, u16, u32, u64, f16, f32, f64, c32, c64] + + @pytest.mark.parametrize( "shape", [ @@ -27,7 +45,7 @@ def test_constant_shape(shape: tuple) -> None: """Test if constant creates an array with the correct shape.""" number = 5.0 - dtype = dtypes.s16 + dtype = s16 result = wrapper.constant(number, shape, dtype) @@ -46,9 +64,9 @@ def test_constant_shape(shape: tuple) -> None: ) def test_constant_complex_shape(shape: tuple) -> None: """Test if constant_complex creates an array with the correct shape.""" - dtype = dtypes.c32 + dtype = c32 - dtype = dtypes.c32 + dtype = c32 rand_array = wrapper.randu((1, 1), dtype) number = wrapper.get_scalar(rand_array, dtype) @@ -71,7 +89,7 @@ def test_constant_complex_shape(shape: tuple) -> None: ) def test_constant_long_shape(shape: tuple) -> None: """Test if constant_long creates an array with the correct shape.""" - dtype = dtypes.s64 + dtype = s64 rand_array = wrapper.randu((1, 1), dtype) number = wrapper.get_scalar(rand_array, dtype) @@ -93,7 +111,7 @@ def test_constant_long_shape(shape: tuple) -> None: ) def test_constant_ulong_shape(shape: tuple) -> None: """Test if constant_ulong creates an array with the correct shape.""" - dtype = dtypes.u64 + dtype = u64 rand_array = wrapper.randu((1, 1), dtype) number = wrapper.get_scalar(rand_array, dtype) @@ -109,7 +127,7 @@ def test_constant_shape_invalid() -> None: """Test if constant handles a shape with greater than 4 dimensions""" with pytest.raises(TypeError): number = 5.0 - dtype = dtypes.s16 + dtype = s16 wrapper.constant(number, invalid_shape, dtype) @@ -117,7 +135,7 @@ def test_constant_shape_invalid() -> None: def test_constant_complex_shape_invalid() -> None: """Test if constant_complex handles a shape with greater than 4 dimensions""" with pytest.raises(TypeError): - dtype = dtypes.c32 + dtype = c32 rand_array = wrapper.randu((1, 1), dtype) number = wrapper.get_scalar(rand_array, dtype) @@ -128,7 +146,7 @@ def test_constant_complex_shape_invalid() -> None: def test_constant_long_shape_invalid() -> None: """Test if constant_long handles a shape with greater than 4 dimensions""" with pytest.raises(TypeError): - dtype = dtypes.s64 + dtype = s64 rand_array = wrapper.randu((1, 1), dtype) number = wrapper.get_scalar(rand_array, dtype) @@ -139,7 +157,7 @@ def test_constant_long_shape_invalid() -> None: def test_constant_ulong_shape_invalid() -> None: """Test if constant_ulong handles a shape with greater than 4 dimensions""" with pytest.raises(TypeError): - dtype = dtypes.u64 + dtype = u64 rand_array = wrapper.randu((1, 1), dtype) number = wrapper.get_scalar(rand_array, dtype) @@ -148,50 +166,47 @@ def test_constant_ulong_shape_invalid() -> None: @pytest.mark.parametrize( - "dtype_index", - [i for i in range(13)], + "dtype", + types, ) -def test_constant_dtype(dtype_index: int) -> None: +def test_constant_dtype(dtype: Dtype) -> None: """Test if constant creates an array with the correct dtype.""" - if dtype_index in [1, 3] or (dtype_index == 2 and not wrapper.get_dbl_support()): + if dtype in [c32, c64] or (dtype == f64 and not wrapper.get_dbl_support()): pytest.skip() - dtype = dtypes.c_api_value_to_dtype(dtype_index) - rand_array = wrapper.randu((1, 1), dtype) value = wrapper.get_scalar(rand_array, dtype) shape = (2, 2) if isinstance(value, (int, float)): result = wrapper.constant(value, shape, dtype) - assert dtypes.c_api_value_to_dtype(wrapper.get_type(result)) == dtype + assert c_api_value_to_dtype(wrapper.get_type(result)) == dtype else: pytest.skip() @pytest.mark.parametrize( - "dtype_index", - [i for i in range(13)], + "dtype", + types, ) -def test_constant_complex_dtype(dtype_index: int) -> None: +def test_constant_complex_dtype(dtype: Dtype) -> None: """Test if constant_complex creates an array with the correct dtype.""" - if dtype_index not in [1, 3] or (dtype_index == 3 and not wrapper.get_dbl_support()): + if dtype not in [c32, c64] or (dtype == c64 and not wrapper.get_dbl_support()): pytest.skip() - dtype = dtypes.c_api_value_to_dtype(dtype_index) rand_array = wrapper.randu((1, 1), dtype) value = wrapper.get_scalar(rand_array, dtype) shape = (2, 2) if isinstance(value, (int, float, complex)): result = wrapper.constant_complex(value, shape, dtype) - assert dtypes.c_api_value_to_dtype(wrapper.get_type(result)) == dtype + assert c_api_value_to_dtype(wrapper.get_type(result)) == dtype else: pytest.skip() def test_constant_long_dtype() -> None: """Test if constant_long creates an array with the correct dtype.""" - dtype = dtypes.s64 + dtype = s64 rand_array = wrapper.randu((1, 1), dtype) value = wrapper.get_scalar(rand_array, dtype) @@ -200,14 +215,14 @@ def test_constant_long_dtype() -> None: if isinstance(value, (int, float)): result = wrapper.constant_long(value, shape, dtype) - assert dtypes.c_api_value_to_dtype(wrapper.get_type(result)) == dtype + assert c_api_value_to_dtype(wrapper.get_type(result)) == dtype else: pytest.skip() def test_constant_ulong_dtype() -> None: """Test if constant_ulong creates an array with the correct dtype.""" - dtype = dtypes.u64 + dtype = u64 rand_array = wrapper.randu((1, 1), dtype) value = wrapper.get_scalar(rand_array, dtype) @@ -216,6 +231,6 @@ def test_constant_ulong_dtype() -> None: if isinstance(value, (int, float)): result = wrapper.constant_ulong(value, shape, dtype) - assert dtypes.c_api_value_to_dtype(wrapper.get_type(result)) == dtype + assert c_api_value_to_dtype(wrapper.get_type(result)) == dtype else: pytest.skip() From bc96cbc734e589a127d3e64428d810bde3628241 Mon Sep 17 00:00:00 2001 From: Chaluvadi Date: Tue, 12 Mar 2024 11:42:09 -0400 Subject: [PATCH 4/9] readability changes pt.2 --- tests/test_constants.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/test_constants.py b/tests/test_constants.py index 929c8ed..e513a0b 100644 --- a/tests/test_constants.py +++ b/tests/test_constants.py @@ -29,7 +29,7 @@ ) -types = [s16, s32, s64, u8, u16, u32, u64, f16, f32, f64, c32, c64] +all_types = [s16, s32, s64, u8, u16, u32, u64, f16, f32, f64, c32, c64] @pytest.mark.parametrize( @@ -66,7 +66,6 @@ def test_constant_complex_shape(shape: tuple) -> None: """Test if constant_complex creates an array with the correct shape.""" dtype = c32 - dtype = c32 rand_array = wrapper.randu((1, 1), dtype) number = wrapper.get_scalar(rand_array, dtype) @@ -167,11 +166,11 @@ def test_constant_ulong_shape_invalid() -> None: @pytest.mark.parametrize( "dtype", - types, + all_types, ) def test_constant_dtype(dtype: Dtype) -> None: """Test if constant creates an array with the correct dtype.""" - if dtype in [c32, c64] or (dtype == f64 and not wrapper.get_dbl_support()): + if is_cmplx_type(dtype) or not is_system_supported(dtype): pytest.skip() rand_array = wrapper.randu((1, 1), dtype) @@ -186,11 +185,11 @@ def test_constant_dtype(dtype: Dtype) -> None: @pytest.mark.parametrize( "dtype", - types, + all_types, ) def test_constant_complex_dtype(dtype: Dtype) -> None: """Test if constant_complex creates an array with the correct dtype.""" - if dtype not in [c32, c64] or (dtype == c64 and not wrapper.get_dbl_support()): + if not is_cmplx_type(dtype) or not is_system_supported(dtype): pytest.skip() rand_array = wrapper.randu((1, 1), dtype) @@ -234,3 +233,14 @@ def test_constant_ulong_dtype() -> None: assert c_api_value_to_dtype(wrapper.get_type(result)) == dtype else: pytest.skip() + + +def is_cmplx_type(dtype: Dtype) -> bool: + return dtype == c32 or dtype == c64 + + +def is_system_supported(dtype: Dtype) -> bool: + if dtype in [f64, c64] and not wrapper.get_dbl_support(): + return False + + return True From a3d051180951504df91ca1cef1b0a4fc759c9801 Mon Sep 17 00:00:00 2001 From: Chaluvadi Date: Mon, 25 Mar 2024 10:12:23 -0400 Subject: [PATCH 5/9] sync() default value fix --- arrayfire_wrapper/lib/create_and_modify_array/manage_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrayfire_wrapper/lib/create_and_modify_array/manage_device.py b/arrayfire_wrapper/lib/create_and_modify_array/manage_device.py index 49a7614..9429e35 100644 --- a/arrayfire_wrapper/lib/create_and_modify_array/manage_device.py +++ b/arrayfire_wrapper/lib/create_and_modify_array/manage_device.py @@ -429,7 +429,7 @@ def set_device(device_id: int, /) -> None: call_from_clib(set_device.__name__, device_id) -def sync(device_id: int, /) -> None: +def sync(device_id: int = -1, /) -> None: """ Blocks until all operations on device are finished. From f84366d4bdc2d0f10a4999d686c0f8273a735f6b Mon Sep 17 00:00:00 2001 From: sakchal Date: Mon, 29 Apr 2024 11:03:27 -0400 Subject: [PATCH 6/9] added opencl functionality and tests within wrapper --- .../lib/interface_functions/opencl.py | 101 +++++++++++++++++- tests/test_opencl.py | 26 +++++ 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 tests/test_opencl.py diff --git a/arrayfire_wrapper/lib/interface_functions/opencl.py b/arrayfire_wrapper/lib/interface_functions/opencl.py index 4640904..321cf18 100644 --- a/arrayfire_wrapper/lib/interface_functions/opencl.py +++ b/arrayfire_wrapper/lib/interface_functions/opencl.py @@ -1 +1,100 @@ -# TODO +import ctypes +from enum import Enum + +from arrayfire_wrapper.lib._utility import call_from_clib + + +class DeviceType(Enum): + CPU = 2 + GPU = 4 + ACC = 8 + UNKNOWN = -1 + + +class PlatformType(Enum): + AMD = 0 + APPLE = 1 + INTEL = 2 + NVIDIA = 3 + BEIGNET = 4 + POCL = 5 + UNKNOWN = -1 + + +def get_context(retain: bool = False) -> int: + """ + source: https://arrayfire.org/docs/group__opencl__mat.htm#gad42de383f405b3e38d6eb669c0cbe2e3 + """ + out = ctypes.c_void_p() + call_from_clib(get_context.__name__, ctypes.pointer(out), retain, clib_prefix="afcl") + return out.value # type: ignore[return-value] + + +def get_queue(retain: bool = False) -> int: + """ + source: https://arrayfire.org/docs/group__opencl__mat.htm#gab1701ef4f2b68429eb31c1e21c88d0bc + """ + out = ctypes.c_void_p() + call_from_clib(get_queue.__name__, ctypes.pointer(out), retain, clib_prefix="afcl") + return out.value # type: ignore[return-value] + + +def get_device_id() -> int: + """ + source: https://arrayfire.org/docs/group__opencl__mat.htm#gaf7258055284e65a8647a49c3f3b9feee + """ + out = ctypes.c_void_p() + call_from_clib(get_device_id.__name__, ctypes.pointer(out), clib_prefix="afcl") + return out.value # type: ignore[return-value] + + +def set_device_id(idx: int) -> None: + """ + source: https://arrayfire.org/docs/group__opencl__mat.htm#ga600361a20ceac2a65590b67fc0366314 + """ + call_from_clib(set_device_id.__name__, ctypes.c_int64(idx), clib_prefix="afcl") + return None + + +def add_device_context(dev: int, ctx: int, que: int) -> None: + """ + source: https://arrayfire.org/docs/group__opencl__mat.htm#ga49f596a4041fb757f1f5a75999cf8858 + """ + call_from_clib( + add_device_context.__name__, ctypes.c_int64(dev), ctypes.c_int64(ctx), ctypes.c_int64(que), clib_prefix="afcl" + ) + return None + + +def set_device_context(dev: int, ctx: int) -> None: + """ + source: https://arrayfire.org/docs/group__opencl__mat.htm#ga975661f2b06dddb125c5d1757160b02c + """ + call_from_clib(set_device_context.__name__, ctypes.c_int64(dev), ctypes.c_int64(ctx), clib_prefix="afcl") + return None + + +def delete_device_context(dev: int, ctx: int) -> None: + """ + source: https://arrayfire.org/docs/group__opencl__mat.htm#ga1a56dcf05099d6ac0a3b7701f7cb23f8 + """ + call_from_clib(delete_device_context.__name__, ctypes.c_int64(dev), ctypes.c_int64(ctx), clib_prefix="afcl") + return None + + +def get_device_type() -> DeviceType: + """ + source: https://arrayfire.org/docs/group__opencl__mat.htm#ga5e360e0fe0eb55d0046191bc3fd6f81d + """ + res = ctypes.c_void_p() + call_from_clib(get_device_type.__name__, ctypes.pointer(res), clib_prefix="afcl") + return DeviceType(res.value) + + +def get_platform() -> PlatformType: + """ + source: https://arrayfire.org/docs/group__opencl__mat.htm#ga5e360e0fe0eb55d0046191bc3fd6f81d&gsc.tab=0 + """ + res = ctypes.c_void_p() + call_from_clib(get_platform.__name__, ctypes.pointer(res), clib_prefix="afcl") + return PlatformType(res.value) diff --git a/tests/test_opencl.py b/tests/test_opencl.py new file mode 100644 index 0000000..517ab02 --- /dev/null +++ b/tests/test_opencl.py @@ -0,0 +1,26 @@ +import arrayfire_wrapper.lib.interface_functions.opencl as cl + + +def test_get_context_type(): + assert isinstance(cl.get_context(), int) + + +def test_get_queue_type(): + assert isinstance(cl.get_queue(), int) + + +def test_get_device_id(): + assert isinstance(cl.get_device_id(), int) + + +def test_set_device_id(): + cl.set_device_id(0) + assert cl.get_device_id() == 0 + + +def test_get_device_type(): + assert cl.get_device_type() == cl.DeviceType.GPU # change according to device + + +def test_get_platform(): + assert cl.get_platform() == cl.PlatformType.INTEL # change according to platform From 4a505dc2967d7866d9fa58cab5a3354246952ae7 Mon Sep 17 00:00:00 2001 From: sakchal Date: Thu, 2 May 2024 11:51:53 -0400 Subject: [PATCH 7/9] fixed test_opencl mypy issues --- tests/test_opencl.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_opencl.py b/tests/test_opencl.py index 517ab02..91dcb58 100644 --- a/tests/test_opencl.py +++ b/tests/test_opencl.py @@ -1,26 +1,26 @@ import arrayfire_wrapper.lib.interface_functions.opencl as cl -def test_get_context_type(): +def test_get_context_type() -> None: assert isinstance(cl.get_context(), int) -def test_get_queue_type(): +def test_get_queue_type() -> None: assert isinstance(cl.get_queue(), int) -def test_get_device_id(): +def test_get_device_id() -> None: assert isinstance(cl.get_device_id(), int) -def test_set_device_id(): +def test_set_device_id() -> None: cl.set_device_id(0) assert cl.get_device_id() == 0 -def test_get_device_type(): +def test_get_device_type() -> None: assert cl.get_device_type() == cl.DeviceType.GPU # change according to device -def test_get_platform(): +def test_get_platform() -> None: assert cl.get_platform() == cl.PlatformType.INTEL # change according to platform From 32c5bf2e425126bc0e5d5a283c764924bb8d0bc9 Mon Sep 17 00:00:00 2001 From: sakchal Date: Wed, 8 May 2024 16:06:26 -0400 Subject: [PATCH 8/9] added interop functionality and tests, edited str_to_dtype function in dtypes, added opencl tests, chaged get_queue and get_context return types to void pointers --- arrayfire_wrapper/dtypes.py | 2 +- .../lib/interface_functions/interop.py | 60 ++++++++++++++++ .../lib/interface_functions/opencl.py | 10 +-- tests/test_interop.py | 72 +++++++++++++++++++ tests/test_opencl.py | 7 +- 5 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 arrayfire_wrapper/lib/interface_functions/interop.py create mode 100644 tests/test_interop.py diff --git a/arrayfire_wrapper/dtypes.py b/arrayfire_wrapper/dtypes.py index 0c8c1b1..31b7af1 100644 --- a/arrayfire_wrapper/dtypes.py +++ b/arrayfire_wrapper/dtypes.py @@ -108,7 +108,7 @@ def c_api_value_to_dtype(value: int) -> Dtype: def str_to_dtype(value: str) -> Dtype: for dtype in supported_dtypes: - if value == dtype.typecode or value == dtype.typename or value == dtype.name: + if value == dtype.typecode or value == dtype.typename or value == dtype.name or value == dtype.c_type: return dtype raise TypeError("There is no supported dtype that matches passed dtype typecode.") diff --git a/arrayfire_wrapper/lib/interface_functions/interop.py b/arrayfire_wrapper/lib/interface_functions/interop.py new file mode 100644 index 0000000..3fb8110 --- /dev/null +++ b/arrayfire_wrapper/lib/interface_functions/interop.py @@ -0,0 +1,60 @@ +import ctypes + +import numpy as np +import pyopencl.array as cl # type: ignore[import-untyped] + +from arrayfire_wrapper.defines import AFArray, CShape +from arrayfire_wrapper.dtypes import c_api_value_to_dtype, str_to_dtype +from arrayfire_wrapper.lib._utility import call_from_clib +from arrayfire_wrapper.lib.create_and_modify_array.manage_array import create_array, get_data_ptr, get_dims, get_type + + +def numpy_to_af_array(np_arr: np.ndarray) -> AFArray: + out = AFArray(0) + shape = np_arr.shape + c_shape = CShape(*shape) + + c_type = np.ctypeslib.as_ctypes_type(np_arr.dtype) + dtype = str_to_dtype(c_type) + + call_from_clib( + create_array.__name__, + ctypes.pointer(out), + np_arr.ctypes.data_as(ctypes.c_void_p), + c_shape.original_shape, + ctypes.pointer(c_shape.c_array), + dtype.c_api_value, + ) + return out + + +def af_to_numpy_array(af_arr: AFArray) -> np.ndarray: + shape = get_dims(af_arr) + dtype = c_api_value_to_dtype(get_type(af_arr)) + typecode = dtype.typecode + + out = np.empty(shape, typecode, "F") + call_from_clib(get_data_ptr.__name__, ctypes.c_void_p(out.ctypes.data), af_arr) + return out + + +def pyopencl_to_af_array(pycl_arr: cl.Array) -> AFArray: + out = AFArray(0) + np_arr = pycl_arr.get() + + shape = np_arr.shape + c_shape = CShape(*shape) + + c_type = np.ctypeslib.as_ctypes_type(np_arr.dtype) + dtype = str_to_dtype(c_type) + + call_from_clib( + create_array.__name__, + ctypes.pointer(out), + np_arr.ctypes.data_as(ctypes.c_void_p), + c_shape.original_shape, + ctypes.pointer(c_shape.c_array), + dtype.c_api_value, + ) + + return out diff --git a/arrayfire_wrapper/lib/interface_functions/opencl.py b/arrayfire_wrapper/lib/interface_functions/opencl.py index 321cf18..9dd8296 100644 --- a/arrayfire_wrapper/lib/interface_functions/opencl.py +++ b/arrayfire_wrapper/lib/interface_functions/opencl.py @@ -21,22 +21,22 @@ class PlatformType(Enum): UNKNOWN = -1 -def get_context(retain: bool = False) -> int: +def get_context(retain: bool = False) -> ctypes.c_void_p: """ source: https://arrayfire.org/docs/group__opencl__mat.htm#gad42de383f405b3e38d6eb669c0cbe2e3 """ out = ctypes.c_void_p() call_from_clib(get_context.__name__, ctypes.pointer(out), retain, clib_prefix="afcl") - return out.value # type: ignore[return-value] + return out # type: ignore[return-value] -def get_queue(retain: bool = False) -> int: +def get_queue(retain: bool = False) -> ctypes.c_void_p: """ source: https://arrayfire.org/docs/group__opencl__mat.htm#gab1701ef4f2b68429eb31c1e21c88d0bc """ out = ctypes.c_void_p() call_from_clib(get_queue.__name__, ctypes.pointer(out), retain, clib_prefix="afcl") - return out.value # type: ignore[return-value] + return out # type: ignore[return-value] def get_device_id() -> int: @@ -45,7 +45,7 @@ def get_device_id() -> int: """ out = ctypes.c_void_p() call_from_clib(get_device_id.__name__, ctypes.pointer(out), clib_prefix="afcl") - return out.value # type: ignore[return-value] + return out # type: ignore[return-value] def set_device_id(idx: int) -> None: diff --git a/tests/test_interop.py b/tests/test_interop.py new file mode 100644 index 0000000..baadcb4 --- /dev/null +++ b/tests/test_interop.py @@ -0,0 +1,72 @@ +import numpy as np +import pyopencl as cl # type: ignore +import pyopencl.array as cl_array # type: ignore + +import arrayfire_wrapper.lib as wrapper +from arrayfire_wrapper.defines import AFArray +from arrayfire_wrapper.dtypes import int16 +from arrayfire_wrapper.lib.create_and_modify_array.manage_array import get_dims, get_numdims +from arrayfire_wrapper.lib.interface_functions.interop import ( # noqa: E501 + af_to_numpy_array, + numpy_to_af_array, + pyopencl_to_af_array, +) + +# flake8: noqa: E203 + + +def test_numpy_to_af_array_type(): + arr = np.array([1, 2, 3, 4]) + + af_array = numpy_to_af_array(arr) + + assert isinstance(af_array, AFArray) + + +def test_af_to_numpy_array_type(): + arr = wrapper.constant(2, (5, 5), int16) + + np_arr = af_to_numpy_array(arr) + + assert isinstance(np_arr, np.ndarray) + + +def test_pyopencl_to_af_array_type(): + ctx = cl.create_some_context() + queue = cl.CommandQueue(ctx) + + host_array = np.array([1, 2, 3, 4]) + + cl_array_device = cl_array.to_device(queue, host_array) + + af_array = pyopencl_to_af_array(cl_array_device) + + assert isinstance(af_array, AFArray) + + +def test_numpy_to_af_array_shape(): + np_arr = np.array([1, 2, 3, 4]) + + af_arr = numpy_to_af_array(np_arr) + + assert get_dims(af_arr)[0 : get_numdims(af_arr)] == np_arr.shape[0 : get_numdims(af_arr)] + + +def test_af_to_numpy_array_shape(): + af_arr = wrapper.constant(2, (5, 5), int16) + + np_arr = af_to_numpy_array(af_arr) + assert np_arr.shape[0 : get_numdims(af_arr)] == get_dims(af_arr)[0 : get_numdims(af_arr)] + + +def test_pyopencl_to_af_array_shape(): + ctx = cl.create_some_context() + queue = cl.CommandQueue(ctx) + + host_array = np.array([1, 2, 3, 4]) + + cl_arr = cl_array.to_device(queue, host_array) + + af_arr = pyopencl_to_af_array(cl_arr) + + assert cl_arr.shape[0 : get_numdims(af_arr)] == get_dims(af_arr)[0 : get_numdims(af_arr)] diff --git a/tests/test_opencl.py b/tests/test_opencl.py index 91dcb58..63aa9da 100644 --- a/tests/test_opencl.py +++ b/tests/test_opencl.py @@ -1,12 +1,15 @@ +import ctypes + import arrayfire_wrapper.lib.interface_functions.opencl as cl def test_get_context_type() -> None: - assert isinstance(cl.get_context(), int) + ptr = cl.get_context() + assert isinstance(ptr, ctypes.c_void_p) def test_get_queue_type() -> None: - assert isinstance(cl.get_queue(), int) + assert isinstance(cl.get_queue(), ctypes.c_void_p) def test_get_device_id() -> None: From 51f16ce28e635c28fa7bfd910453e7f8c7b45a69 Mon Sep 17 00:00:00 2001 From: sakchal Date: Wed, 8 May 2024 16:09:26 -0400 Subject: [PATCH 9/9] added return types for interop tests --- tests/test_interop.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_interop.py b/tests/test_interop.py index baadcb4..80c4329 100644 --- a/tests/test_interop.py +++ b/tests/test_interop.py @@ -15,7 +15,7 @@ # flake8: noqa: E203 -def test_numpy_to_af_array_type(): +def test_numpy_to_af_array_type() -> None: arr = np.array([1, 2, 3, 4]) af_array = numpy_to_af_array(arr) @@ -23,7 +23,7 @@ def test_numpy_to_af_array_type(): assert isinstance(af_array, AFArray) -def test_af_to_numpy_array_type(): +def test_af_to_numpy_array_type() -> None: arr = wrapper.constant(2, (5, 5), int16) np_arr = af_to_numpy_array(arr) @@ -31,7 +31,7 @@ def test_af_to_numpy_array_type(): assert isinstance(np_arr, np.ndarray) -def test_pyopencl_to_af_array_type(): +def test_pyopencl_to_af_array_type() -> None: ctx = cl.create_some_context() queue = cl.CommandQueue(ctx) @@ -44,7 +44,7 @@ def test_pyopencl_to_af_array_type(): assert isinstance(af_array, AFArray) -def test_numpy_to_af_array_shape(): +def test_numpy_to_af_array_shape() -> None: np_arr = np.array([1, 2, 3, 4]) af_arr = numpy_to_af_array(np_arr) @@ -52,14 +52,14 @@ def test_numpy_to_af_array_shape(): assert get_dims(af_arr)[0 : get_numdims(af_arr)] == np_arr.shape[0 : get_numdims(af_arr)] -def test_af_to_numpy_array_shape(): +def test_af_to_numpy_array_shape() -> None: af_arr = wrapper.constant(2, (5, 5), int16) np_arr = af_to_numpy_array(af_arr) assert np_arr.shape[0 : get_numdims(af_arr)] == get_dims(af_arr)[0 : get_numdims(af_arr)] -def test_pyopencl_to_af_array_shape(): +def test_pyopencl_to_af_array_shape() -> None: ctx = cl.create_some_context() queue = cl.CommandQueue(ctx)