question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Directive for force-compiling code branches for different bint-parameters?

See original GitHub issue

Not sure if this is feasible, but I had the following situation while working on pandas hashtable code recently (simplified a bit from pandas-dev/pandas#22986 for clarity):

Two methods had substantial code overlap, with the difference being easily absorbed into a bint parameter - in this case, whether the unique method returns an inverse or not. It would be very desirable from a clarity/readability/maintenance perspective to unify the code for those two methods.

I tried unifying these functions, but there was a perf-hit for the simpler case (no inverse) of about 10%, which is too much for just always calculating it by default for such a central method.

I then tried (very naively) to get cython to compile the different code branches as follows:

    def _unique(self, ndarray[object] values, bint return_inverse=False):
        [...]
        with nogil:
            for i in range(n):
                [actual computation]
                if return_inverse:
                    [calculate inverse]

    def unique(self, ndarray[object] values, bint return_inverse=False):
        # define separate functions with/without inverse to force compilation
        # of the different code paths for boolean "return_inverse"
        if return_inverse:
            return self._unique_with_inverse(values)
        return self._unique_no_inverse(values)

    def _unique_no_inverse(self, const {{dtype}}_t[:] values):
        return self._unique(values, return_inverse=False)

    def _unique_with_inverse(self, const {{dtype}}_t[:] values):
        return self._unique(values, return_inverse=True)

but the perf penalty remained.

Summing up, it would be awesome to be able to do something like (the example below borrows from @pytest.mark.parametrize, but the exact syntax is not relevant to me):

    @cython.force_compile('return_inverse', [False])
    def unique(self, ndarray[object] values, bint return_inverse=False):
        [...]
        with nogil:
            for i in range(n):
                [compute]
                if return_inverse:
                    [calculate inverse]

with the idea being to both unify the code and maintain perf in the case where the return_inverse-branch doesn’t need to be touched at all.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
h-vetinaricommented, Sep 9, 2020

Thanks for the tip @jakirkham, maybe I’ll have some time to improve that old pandas PR. 😃

0reactions
jakirkhamcommented, Sep 5, 2020

FWIW there is actually a neat trick that one can do in Cython using fused types, which is similar to C++'s SFINAE like what has been used with enable_if. Here’s a short example of how this works below.

cdef struct bint_false_type:
    char empty                               # need something as empty `struct`s are not valid

cdef struct bint_true_type:
    char empty                               # ditto

cdef fused param_bint_type:                  # fuse `True` and `False` types to allow selection between them
     bint_false_type
     bint_true_type


cdef inline bint cfunc(param_bint_type* p):  # include unused argument of fused type for selection
    if param_bint_type is bint_true_type:    # compile time dispatching on type
        return True
    else:
        return False

def func(bint b):
    if b:
        return cfunc(<bint_true_type*>NULL)  # cast `NULL` pointer to needed type for selection
    else:
        return cfunc(<bint_false_type*>NULL)
Read more comments on GitHub >

github_iconTop Results From Across the Web

dafi36-2406.pdf - Air Force
This memorandum establishes this instruction as a Department of the Air Force instruction (DAFI); implements officer evaluation static close out ...
Read more >
Conditional Execution - an overview | ScienceDirect Topics
The ARM allows any instruction, including branches, to be executed conditionally. This allows branches to be conditional, as well as data operations. Fig....
Read more >
Directive (EU) 2018/1972 of the European Parliament and of ...
This Directive is part of a 'Regulatory Fitness' (REFIT) exercise, the scope of which includes four Directives, namely 2002/19/EC, 2002/20/EC, ...
Read more >
Executive Order on Advancing Effective, Accountable Policing ...
My Administration will fully implement the First Step Act, including by supporting sentencing reductions in appropriate cases and by allowing ...
Read more >
2 CFR Part 200 -- Uniform Administrative Requirements, Cost ...
The instrument is the grant agreement, cooperative agreement, other agreement for assistance covered in paragraph (2) of the definition of Federal financial ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found