Skip to content

Optimize Affine2D transforms #22191

Open
Open

Description

@QuLogic

To address @timhoffm's other comment ("Does it still make sense to keep Affine2D._mtx as a numpy array if we only do element-wise operations?"): I'm quite convinced the whole transform stack would be faster if the transformation matrix was not a numpy array (because 3x3 is a size where the numpy's overhead is generally bigger than the gains from vectorization), but changing everything at once (even better would be to move things to C, but using plain C structs (or equivalently C++ objects) to store the coefficients) would be quite a big PR. So I'm doing the easy parts first :-)

Originally posted by @anntzer in #22119

Activity

  1. QuLogic commented on Jan 11, 2022

    @QuLogic
    MemberAuthor

    I also noted that there exist several packages that do affine transforms already. I have not attempted any conversions, and they may not be any better, but might be useful as inspiration.

    There are some pure Python packages:

    • affine - Matrices for affine transformations on the plane
    • matrix-47 - General matrix math

    Some compiled options:

    • affine-transform - Parallel affine transforms using C++17 and OpenMP
    • Pyrr - 3D mathematical functions using NumPy (might be similar to ours though)
    • cython-blis - Fast matrix-multiplication as a self-contained Python library (not affine specific)
    • eigency - Cython interface to Eigen library

    And some non-Python things that would need wrappers:

  2. QuLogic commented on Dec 20, 2023

    @QuLogic
    MemberAuthor

    Since pybind11 has native support for Eigen, I've put together a branch https://github.com/QuLogic/matplotlib/tree/eigen-transform that attempts to use it. There are a few minor issues that need to be fixed, but it passes most tests now.

    However, I've noticed that there is a cast to a NumPy array in the path extension here:

    PyArrayObject *array = (PyArrayObject *)PyArray_ContiguousFromAny(obj, NPY_DOUBLE, 2, 2);
    if (array == NULL) {
    return 0;
    }

    which means we miss out on avoiding NumPy right now. This will be made easier once #27087 is complete.

    I've not run any benchmarks yet, but at least this points out the pain points with doing this change (and we got #27511 out of it.)

  3. QuLogic commented on Dec 20, 2023

    @QuLogic
    MemberAuthor

    Also, taking a quick look at Agg's trans_affine, it looks to be fairly similar to Eigen. It may be just as easy to implement that way, and not require the addition of Eigen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions