# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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 pytest
import nanoarrow as na
from nanoarrow import device
def test_cpu_device():
cpu = device.cpu()
assert cpu.device_type_id == 1
assert cpu.device_type == device.DeviceType.CPU
assert cpu.device_id == -1
assert "device_type: CPU <1>" in repr(cpu)
cpu2 = device.resolve(1, 0)
assert cpu2 is cpu
def test_c_device_array():
# Unrecognized arguments should be passed to c_array() to generate CPU array
darray = device.c_device_array([1, 2, 3], na.int32())
assert darray.device_type_id == 1
assert darray.device_type == device.DeviceType.CPU
assert darray.device_id == -1
assert "device_type: CPU <1>" in repr(darray)
assert darray.schema.format == "i"
assert len(darray.array) == 3
assert darray.array.device_type == device.cpu().device_type
assert darray.array.device_id == device.cpu().device_id
darray_view = darray.view()
assert len(darray_view) == 3
assert list(darray_view.buffer(1)) == [1, 2, 3]
# A CDeviceArray should be returned as is
assert device.c_device_array(darray) is darray
# A CPU device array should be able to export to a regular array
array = na.c_array(darray)
assert array.schema.format == "i"
assert array.buffers == darray.array.buffers
def test_c_device_array_from_dlpack(cuda_device):
from nanoarrow.device import DeviceType
cp = pytest.importorskip("cupy")
if not cuda_device:
pytest.skip("CUDA device not available")
assert cuda_device.device_type == DeviceType.CUDA
assert cuda_device.device_id == 0
gpu_array = cp.array([1, 2, 3])
darray = device.c_device_array(gpu_array)
assert isinstance(darray, device.CDeviceArray)
assert darray.device_type == DeviceType.CUDA
assert len(darray.array) == 3
assert darray.array.null_count == 0
gpu_buffer_view = darray.array.view().buffer(1)
cp.testing.assert_array_equal(cp.from_dlpack(gpu_buffer_view), gpu_array)
def test_c_device_array_protocol():
# Wrapper to prevent c_device_array() from returning early when it detects the
# input is already a CDeviceArray
class CDeviceArrayWrapper:
def __init__(self, obj):
self.obj = obj
def __arrow_c_device_array__(self, requested_schema=None):
return self.obj.__arrow_c_device_array__(requested_schema=requested_schema)
darray = device.c_device_array([1, 2, 3], na.int32())
wrapper = CDeviceArrayWrapper(darray)
darray2 = device.c_device_array(wrapper)
assert darray2.schema.format == "i"
assert len(darray2.array) == 3
assert darray2.array.buffers == darray.array.buffers
with pytest.raises(NotImplementedError):
device.c_device_array(wrapper, na.int64())