Skip to content

Provide Python hook for asynchronous exception handler #269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
oleksandr-pavlyk opened this issue Feb 3, 2021 · 7 comments
Closed

Provide Python hook for asynchronous exception handler #269

oleksandr-pavlyk opened this issue Feb 3, 2021 · 7 comments

Comments

@oleksandr-pavlyk
Copy link
Contributor

When creating a SyclQueue, or SyclContext one should be able to define an exception handler in Python.

One operation that can through an exception, or asynchronous SYCL exception should be wrapped in try{ } catch(std::exception &e) { }.

Per IntelPython/dpnp#201 (comment) the asynchronous exception can be caught, converted to dpctl.SyclException instances, and provided to a user-defined function for handling.

@diptorupd
Copy link
Contributor

@oleksandr-pavlyk I was thinking of implementing it as follows:

In the C API, add a functor that is initialized with a Python callback function and invokes the callback inside a async_handler function. In the Cython-layer, we need a function that switches over the error codes passed to the callback function and then
raise a PyErr.

I am actually not totally sure on the Cython/Python side of things, but for the C-API, following is what I had in mind:

#include <iostream>
#include <functional>
#include <CL/sycl.hpp>

class invalid_kernel;
using namespace cl::sycl;

namespace {
void py_exception_handler (int err_code) {
    std::cerr << "This is the callback that Cython passed to  dpctl C-API."
                 "Error code (" << err_code << ")\n";
}

struct DPCTL_AsycErrorHandler {
    void (*exception_handler)(int err_code) = nullptr;

    DPCTL_AsycErrorHandler (void (*py_err_handler)(int err_code))
    :  exception_handler(py_err_handler)
    {  }

    void operator() (const exception_list &exceptions) {
        for (std::exception_ptr const& e : exceptions) {
            try {
                std::rethrow_exception(e);
            } catch(cl::sycl::exception const& e) {
                std::cerr << "ASYNC error handling\n";
                std::cerr << "Caught asynchronous SYCL exception:\n"
                          << e.what() << std::endl;
                if(exception_handler) {
                    // In the spec but not supported yet
                    //auto err_code = e.code().value();
                    auto err_code = -1;
                    exception_handler(err_code);
                }
            }
        }
    }
};
} /* end of anonymous namespace */

int main(int, char**) {
    cl::sycl::queue queue(cl::sycl::default_selector{}, 
                          DPCTL_AsycErrorHandler(py_exception_handler));

    queue.submit([&] (cl::sycl::handler& cgh) {
        auto range = cl::sycl::nd_range<1>(cl::sycl::range<1>(1), cl::sycl::range<1>(10));
        cgh.parallel_for<class invalid_kernel>(range, [=] (cl::sycl::nd_item<1>) {});
    });

    try {
        queue.wait_and_throw();
    } catch (cl::sycl::exception const& e) {
        std::cerr << "Caught synchronous SYCL exception:\n"  << e.what() << std::endl;
    }
    return 0;
}

@diptorupd
Copy link
Contributor

diptorupd commented Feb 10, 2021

@oleksandr-pavlyk I pushed an as yet untested implementation of DPCTLSyclQueue_Create to my WIP branch that implements the async_handler feature. I expect this function to replace the DPCTLQueueMgr_GetQueueFromContextAndDevice function and to be used everywhere we create queues in C API and Cython.

Will appreciate your feedback.

@oleksandr-pavlyk
Copy link
Contributor Author

@diptorupd The sycl::exception currently provides get_cl_code() method.

@oleksandr-pavlyk
Copy link
Contributor Author

Configurable Python async error handler is not as useful as I thought it might be.

Instead of allowing a user to write one, dpctl provides a default async error handler in branch featute/queue_manager_v2

@oleksandr-pavlyk
Copy link
Contributor Author

dpctl already supports setting of sycl::async_handler in sycl::queue and sycl::context. The default handler implemented in dpctl/_sycl_queue.pyx` is used.

It is not user configurable.

C-API should support custom synchronous error handler to allow information contained in C++ exceptions to cross C-interface.
The handler should take an error code enum and a string (e.what()) as artguments and return void.

The default handler for C user may be to echo to std::cerr, but dpctl should set to translate error code & error message to Python exceptions.

@diptorupd
Copy link
Contributor

@oleksandr-pavlyk @vlad-perevezentsev Is solving this issue still on the cards? Can we close the issue based on Vlad's error handler redesign?

@oleksandr-pavlyk
Copy link
Contributor Author

Closing as no longer relevant. The async exception handler is a C++ callable which takes a C++ argument. Passing such a callable from C (created in Python, but most importantly, passed to queue construction via C interface just does not work).

Moreover, we could not identify sensible use-cases that would become possible should custom async handler be available for Python user to program.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants