Skip to content
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

Performance hints for nogil functions requiring exception checks #5673

Merged
merged 14 commits into from Sep 29, 2023

Conversation

da-woods
Copy link
Contributor

@da-woods da-woods commented Sep 1, 2023

I've created a "not warning" category of message to alert users to performance improvements. It won't cause -Werror to fail and it can be disabled.

Based on #5324 (comment) it would be good if it could appear in annotated html files. However, that's

  1. beyond me right now (but not excluded in future)
  2. probably not hugely useful to most users with existing code bases since they won't be looking at annotated files

I'm not sure this is the perfect solution, but I think some kind of diagnostic is necessary to help people with this.

Copy link
Contributor

@scoder scoder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. Does this also solve the problem that we issue warnings from within utility code?

Comment on lines 934 to 946
pos_filetype = pos[0]._file_type if pos else None
if (type.exception_check and type.exception_value is None and type.nogil and
not pos[0].is_utility_code and
defining and # don't warn about external functions here - the user likely can't do anything
pos_filetype != 'pxd' # again, exclude extern functions (is_pxd is unreliable here)
):
msg = (
"Exception check on '%s' will always require the GIL to be acquired. Possible solutions:"
"\n\t1. Declare the function as 'noexcept' if you're sure the function should not raise exceptions."
) % name
if type.return_type.is_void:
msg += "\n\t2. Return a dummy integer for Cython to use as an exception flag."
performance_hint(pos, msg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that you managed to write more or less the same message twice in two entirely different wordings but with just a few additional conditions in the second incarnation, this loudly screams for a shared helper function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, "requires to be reacquired" sounds funny. Maybe there's a different word that you could use for one or the other.

@@ -931,6 +931,19 @@ def declare_cfunction(self, name, type, pos,
var_entry.scope = entry.scope
entry.as_variable = var_entry
type.entry = entry
pos_filetype = pos[0]._file_type if pos else None
if (type.exception_check and type.exception_value is None and type.nogil and
not pos[0].is_utility_code and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in_utility_code would read a bit better here, I think. Just a suggestion.

runtests.py Outdated Show resolved Hide resolved
@da-woods
Copy link
Contributor Author

da-woods commented Sep 1, 2023

Does this also solve the problem that we issue warnings from within utility code?

Not in this PR. But it could probably be used as a mechanism to do so.

@@ -284,3 +298,14 @@ def reset():

def get_errors_count():
return threadlocal.cython_errors_count

def noexcept_performance_hint_helper(pos, function_name = None, void_return = False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. "xyz_helper" is rarely a good name for a function since every function helps with something. That doesn't tell much about what it actually does. Actual verbs like write_ or issue_ seem better.
Suggested change
def noexcept_performance_hint_helper(pos, function_name = None, void_return = False):
def write_noexcept_performance_hint(pos, function_name=None, void_return=False):
  1. This seems too specific for Errors.py. You probably considered a couple of places before you put it here, and I agree that it's not easy to decide. But maybe somewhere in PyrexTypes.py? The hint that we give seems mostly related to C function types. I would consider adding a new module for this, but I'm not sure that we will have many cases where we issue the same hint from more than one place. We'll see about that…

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a new module (and also moved one function in ExprNodes that seemed to fit in the same place).

If you think that's excessive I can put it in PyrexTypes though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed my mind because it caused a circular import and just moved it to PyrexTypes

Cython/Compiler/PyrexTypes.py Outdated Show resolved Hide resolved
if (type.exception_check and type.exception_value is None and type.nogil and
not pos[0].in_utility_code and
defining and # don't warn about external functions here - the user likely can't do anything
pos_filetype != 'pxd' # again, exclude extern functions (is_pxd is unreliable here)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Does this also exclude inline functions in .pxd files?
  2. Why is is_pxd unreliable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Does this also exclude inline functions in .pxd files?

Yes - intentionally (I'm working on the basis that anything in a pxd is likely something the user doesn't control, and that they get a message when they use it anyway)

  1. Why is is_pxd unreliable?

Not sure off the top of my head, but it didn't seem to be set in the example that I tested. I'll go back and see if I can fix that though.

(Will also come back to the other two comments later)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like in_pxd means that Cython generates code to cimport the function by declaring function pointers (which conflicts with inline). I've had a go at trying to fix that so it's probably a bit better.

runtests.py Outdated Show resolved Hide resolved
runtests.py Outdated Show resolved Hide resolved
runtests.py Outdated Show resolved Hide resolved
runtests.py Outdated
Comment on lines 669 to 671
def getperformancehints(self):
return self._collect()[2]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used anywhere? Do we need to add it? (And, BTW, are the other two corresponding methods really used anywhere?)

runtests.py Outdated
Comment on lines 990 to 1001
expect_errors=False, expect_warnings=False, annotate=False, cleanup_workdir=True,
expect_errors=False, expect_warnings=False, expect_perf_hints=False,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it's time to clean this up and pass a single expect_log=('warnings', 'errors') option around (name is up for debate…). We're really carrying around a lot of options by now, and I feel bad every time I add one to the list.

Doesn't have to be in this PR, though. Adding this one doesn't make it much worse.

da-woods and others added 4 commits September 4, 2023 08:49
Co-authored-by: scoder <stefan_ml@behnel.de>
Co-authored-by: scoder <stefan_ml@behnel.de>
@scoder scoder merged commit 401e880 into cython:master Sep 29, 2023
76 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants