From 8c198e1deeeda62ed4e1ab4b1a33889f328c7972 Mon Sep 17 00:00:00 2001 From: Ben Frederickson Date: Tue, 5 Mar 2024 09:36:45 -0800 Subject: [PATCH] add errror text to python exceptions --- python/cuvs/cuvs/common/CMakeLists.txt | 2 +- python/cuvs/cuvs/common/c_api.pxd | 1 + python/cuvs/cuvs/common/exceptions.pyx | 37 ++++++++++++++++++++++ python/cuvs/cuvs/neighbors/cagra/cagra.pyx | 37 +++++++--------------- rust/cuvs/src/cagra/index_params.rs | 2 +- 5 files changed, 51 insertions(+), 28 deletions(-) create mode 100644 python/cuvs/cuvs/common/exceptions.pyx diff --git a/python/cuvs/cuvs/common/CMakeLists.txt b/python/cuvs/cuvs/common/CMakeLists.txt index 2cf1ff19c..b477fdb32 100644 --- a/python/cuvs/cuvs/common/CMakeLists.txt +++ b/python/cuvs/cuvs/common/CMakeLists.txt @@ -13,7 +13,7 @@ # ============================================================================= # Set the list of Cython files to build -set(cython_sources cydlpack.pyx) +set(cython_sources cydlpack.pyx exceptions.pyx) set(linked_libraries cuvs::cuvs cuvs_c) # Build all of the Cython targets diff --git a/python/cuvs/cuvs/common/c_api.pxd b/python/cuvs/cuvs/common/c_api.pxd index 6addbf16e..e4e62bf94 100644 --- a/python/cuvs/cuvs/common/c_api.pxd +++ b/python/cuvs/cuvs/common/c_api.pxd @@ -30,3 +30,4 @@ cdef extern from "cuvs/core/c_api.h": cuvsError_t cuvsResourcesCreate(cuvsResources_t* res) cuvsError_t cuvsResourcesDestroy(cuvsResources_t res) cuvsError_t cuvsStreamSet(cuvsResources_t res, cudaStream_t stream) + const char * cuvsGetLastErrorText() diff --git a/python/cuvs/cuvs/common/exceptions.pyx b/python/cuvs/cuvs/common/exceptions.pyx new file mode 100644 index 000000000..603e0711b --- /dev/null +++ b/python/cuvs/cuvs/common/exceptions.pyx @@ -0,0 +1,37 @@ +# +# Copyright (c) 2024, NVIDIA 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. +# +# cython: language_level=3 + +from cuvs.common.c_api cimport cuvsError_t, cuvsGetLastErrorText + + +class CuvsException(Exception): + pass + + +def get_last_error_text(): + """ returns the last error description from the cuvs c-api """ + cdef const char* c_err = cuvsGetLastErrorText() + if c_err is NULL: + return + cdef bytes err = c_err + return err.decode("utf8") + + +def check_cuvs(status: cuvsError_t): + """ Converts a status code into an exception """ + if status == cuvsError_t.CUVS_ERROR: + raise CuvsException(get_last_error_text()) diff --git a/python/cuvs/cuvs/neighbors/cagra/cagra.pyx b/python/cuvs/cuvs/neighbors/cagra/cagra.pyx index bf17fe6a5..04031414e 100644 --- a/python/cuvs/cuvs/neighbors/cagra/cagra.pyx +++ b/python/cuvs/cuvs/neighbors/cagra/cagra.pyx @@ -52,6 +52,8 @@ from cuvs.common.c_api cimport ( cuvsResourcesCreate, ) +from cuvs.common.exceptions import check_cuvs + cdef class IndexParams: """ @@ -124,19 +126,13 @@ cdef class Index: cdef bool trained def __cinit__(self): - cdef cuvsError_t index_create_status - index_create_status = cuvsCagraIndexCreate(&self.index) self.trained = False - - if index_create_status == cuvsError_t.CUVS_ERROR: - raise RuntimeError("Failed to create index.") + check_cuvs(cuvsCagraIndexCreate(&self.index)) def __dealloc__(self): cdef cuvsError_t index_destroy_status if self.index is not NULL: - index_destroy_status = cuvsCagraIndexDestroy(self.index) - if index_destroy_status == cuvsError_t.CUVS_ERROR: - raise Exception("Failed to deallocate index.") + check_cuvs(cuvsCagraIndexDestroy(self.index)) @property def trained(self): @@ -203,9 +199,7 @@ def build_index(IndexParams index_params, dataset, resources=None): cdef cuvsResources_t res_ cdef cuvsError_t cstat - cstat = cuvsResourcesCreate(&res_) - if cstat == cuvsError_t.CUVS_ERROR: - raise RuntimeError("Error creating Device Reources.") + check_cuvs(cuvsResourcesCreate(&res_)) cdef Index idx = Index() cdef cuvsError_t build_status @@ -214,17 +208,13 @@ def build_index(IndexParams index_params, dataset, resources=None): cdef cuvsCagraIndexParams* params = index_params.params with cuda_interruptible(): - build_status = cuvsCagraBuild( + check_cuvs(cuvsCagraBuild( res_, params, dataset_dlpack, idx.index - ) - - if build_status == cuvsError_t.CUVS_ERROR: - raise RuntimeError("Index failed to build.") - else: - idx.trained = True + )) + idx.trained = True return idx @@ -451,9 +441,7 @@ def search(SearchParams search_params, cdef cuvsResources_t res_ cdef cuvsError_t cstat - cstat = cuvsResourcesCreate(&res_) - if cstat == cuvsError_t.CUVS_ERROR: - raise RuntimeError("Error creating Device Reources.") + check_cuvs(cuvsResourcesCreate(&res_)) # todo(dgd): we can make the check of dtype a parameter of wrap_array # in RAFT to make this a single call @@ -487,16 +475,13 @@ def search(SearchParams search_params, cydlpack.dlpack_c(distances_cai) with cuda_interruptible(): - search_status = cuvsCagraSearch( + check_cuvs(cuvsCagraSearch( res_, params, index.index, queries_dlpack, neighbors_dlpack, distances_dlpack - ) - - if search_status == cuvsError_t.CUVS_ERROR: - raise RuntimeError("Search failed.") + )) return (distances, neighbors) diff --git a/rust/cuvs/src/cagra/index_params.rs b/rust/cuvs/src/cagra/index_params.rs index 656ab4a9c..7ff68d3f3 100644 --- a/rust/cuvs/src/cagra/index_params.rs +++ b/rust/cuvs/src/cagra/index_params.rs @@ -69,7 +69,7 @@ impl fmt::Debug for IndexParams { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // custom debug trait here, default value will show the pointer address // for the inner params object which isn't that useful. - write!(f, "IndexParams {{ params: {:?} }}", unsafe { *self.0 }) + write!(f, "IndexParams({:?})", unsafe { *self.0 }) } }