GeezerVison is showing github.com — gh-117578: Fix inlining regression in PyType_GetModuleByDef() by neonene · Pull Request #123100 · python/cpython
Conversation
neonene
commented
Aug 17, 2024
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
On main and 3.13, there are cases where the get_module_by_def function in typeobject.c is not inlined in its wrapper functions:
| Wrappers |
Windows |
callee: get_module_by_def() |
PyType_GetModuleByDef() |
Release |
/Ob2:called /Ob3:inlined |
|
PGO |
inlined |
_PyType_GetModuleByDef2() |
Release |
/Ob2:called /Ob3:inlined |
|
PGO |
called |
Non-builtin modules can have extra function-call overheads, where the wrappers cannot be inlined.
This PR specifies Py_ALWAYS_INLINE to the callee.
cc @encukou
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
neonene
changed the title
gh-117578: Fix inlining regression in PyType_GetModuleByDef() family
gh-117578: Fix inlining regression in PyType_GetModuleByDef()
Aug 17, 2024
|
Hm, it doesn't sound right to override profile-guided optimization, especially since test_decimal (the only current caller of _PyType_GetModuleByDef2) is in the PGO test set.
Does this PR have a significant performance impact?
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
neonene
commented
Aug 20, 2024
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
It is mentioned on the faster-cpython repo that the telco test has slowed down a lot.
According to MSVC, the module state access counts were:
Function / breakdown entry-cnt alternative access
----------------------- --------- ---------------------------
PyType_GetModuleByDef() 6852643
convert_op 2971848 via context object
PyDecType_New 1651188 via context object (partial)
dec_addstatus 1651188 via context object (partial)
current_context 1486221 via context object (partial)
dec_mpd_qquantize 247731 METH_METHOD
ctx_mpd_qquantize 165000 METH_METHOD
...
_PyType_GetModuleByDef2() 1073193
nm_mpd_qadd 660462
nm_mpd_qmul 412731
Tested with the /Ob3 option, switching the inlining specifier: f740a5d. My Release/PGO builds on Windows get slower using TLS version of PyThreadState_Get(), which is also observed at #103324 (comment). If *nix OSes are in good health with TLS, I guess I also need to run the telco with a good condition (without TLS):
|
sub |
|
|
|
GetModuleByDef |
call |
inline |
inline |
|
GetModuleByDef2 |
call |
call |
inline |
|
|
|
|
|
|
| normal 3.14 |
perf |
|
|
(the higher, the faster) |
|
1.00x |
(base) |
1.01x |
|
|
1.03x |
1.05x |
1.08x |
respect alternative |
|
|
|
|
|
| less TLS overhead |
perf |
|
|
(experiment) |
|
1.05x |
1.05x |
1.06x |
|
|
1.08x |
1.08x |
1.08x |
respect alternative |
| module state access |
normal |
TLS-less |
|
| current |
(base) |
1.05x |
|
| This PR |
1.01x |
1.06x |
|
| PyThreadState_Get() |
1.05x |
1.04x |
example patches |
| PR with alternatives |
1.08x |
1.08x |
|
| global state |
1.08x |
1.11x |
|
| static type (GC unused) |
1.14x |
1.14x |
taken from 3.12 |
This patch would need to be applied if we wanted as much speed as the global state access on Windows, which has little effect alone (1%) for some reason.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Windows PGO:
- telco: 9.21 ms +- 0.12 ms -> 9.02 ms +- 0.09 ms: 1.02x faster
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
neonene
commented
Aug 21, 2024
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
Is it acceptable that test_decimal.py has a test case like below, instead of touching the C code?
@requires_cdecimal
class CArithmeticOperatorsTest(ArithmeticOperatorsTest, unittest.TestCase):
...
@unittest.skipIf(not test.support.PGO, 'PGO training only')
def test_excecise_binop(self):
Decimal = self.decimal.Decimal
d = Decimal('11.1')
for i in range(500000):
1 + d # at least 300000 times
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
I'll try PyType_GetBaseByToken() version.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Closing in favor of proposing the PyType_GetBaseByToken() version, which can supersede _PyType_GetModuleByDef2() on PGO and Relase(/Ob3) builds.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Reviewers
markshannon
Awaiting requested review from markshannon
markshannon is a code owner
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|