GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-117578: Fix inlining regression in PyType_GetModuleByDef() by neonene · Pull Request #123100 · python/cpython

Conversation

@neonene

@neonene neonene commented Aug 17, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

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

  • Issue: PyType_GetModuleByDef family for binary functions performance #117578

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@neonene
add Py_ALWAYS_INLINE
01c3322
@neonene
neonene requested a review from markshannon as a code owner August 17, 2024 11:40
@bedevere-app bedevere-app Bot mentioned this pull request Aug 17, 2024
PyType_GetModuleByDef family for binary functions performance #117578
Closed
@bedevere-app bedevere-app Bot added the awaiting review label Aug 17, 2024
@neonene neonene changed the title gh-117578: Fix inlining regression in PyType_GetModuleByDef() family gh-117578: Fix inlining regression in PyType_GetModuleByDef() Aug 17, 2024
@encukou encukou added the skip news label Aug 19, 2024
@encukou

encukou commented Aug 19, 2024

Copy link
Copy Markdown
Member

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?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

neonene added 3 commits August 20, 2024 19:18
@neonene
benchmark setup: /Ob3, __declspec(noinline)
f740a5d
@neonene
unsafe experiment: do not respect TLS access
6e62c38
@neonene
revert benchmark stuff
89754d7
@neonene

neonene commented Aug 20, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

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.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@neonene

neonene commented Aug 20, 2024

Copy link
Copy Markdown
Contributor Author

Windows PGO:
- telco: 9.21 ms +- 0.12 ms -> 9.02 ms +- 0.09 ms: 1.02x faster

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@neonene

neonene commented Aug 21, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

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
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@neonene

neonene commented Aug 21, 2024

Copy link
Copy Markdown
Contributor Author

I'll try PyType_GetBaseByToken() version.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@neonene

neonene commented Aug 26, 2024

Copy link
Copy Markdown
Contributor Author

Closing in favor of proposing the PyType_GetBaseByToken() version, which can supersede _PyType_GetModuleByDef2() on PGO and Relase(/Ob3) builds.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@neonene neonene closed this Aug 26, 2024
@neonene
neonene deleted the bydef-inline branch September 20, 2024 03:42
@neonene neonene mentioned this pull request Sep 27, 2024
gh-124688: _decimal: Get a module state from ctx objects for performance #124691
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@markshannon 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

Labels

awaiting review skip news

Projects

None yet

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.

2 participants

@neonene @encukou
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.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.