只需调整Libpython的一些编译选项,Python速度更快1.3倍

2021-06-13 09:35:16

由vstinner 2019-12-05 16:00创建,最后改变了vstinner 2020-10-27 02:07。此问题现已关闭。

Fedora Packaging已被修改为使用-fno-semante-Intertheation标志编译libpython:它使Python能够更快地达到1.3倍,而无需触摸C代码的任何行!请参阅PyperFormance结果: https://fedoraproject.org/wiki/changes/pythonnosemanticintalpositionspeedup#benefit_to_fedora. 主要缺点是 - 使用LD_PRELOAD预加载的自定义库可防止覆盖Python符号的-Fno-seamante。例如,覆盖pyerr_occurred()函数。 我们(Fedora更改的作者)无法找到LD_PRELOAD的任何用例。 要诚实地,我在过去10年中找到了*用户在使用LD_PRELOAD以跟踪Python 2.7中的内存分配。使用Python 3使用PEP 445不再相关,PEP 445提供支持的C API以覆盖Python内存分配器或在Python内存分配器上安装挂钩。此外,TraceMalloc是跟踪内存分配的好方法。 是否有人知道LD_PRELOAD for libpython的任何特殊用途? 要清楚:-fno-semantic-Interthition仅影响libpython。所有其他库仍然尊重LD_PRELOAD。例如,仍然可以覆盖Glibc Malloc /免费。 为什么-Fno-indantic-Interthion使Python更快?有多种原因。因为所有这些,libpython对libpython进行了很多函数调用。就像真的很多,特别是在热代码路径中。没有 - 语义插入,对libpython的函数调用需要通过"插入"例如"程序链接表" (PLT)Linux的间接。它可以防止功能内联对性能产生重大影响(错过优化)。简而言之,即使与PGO和LTO,Libpython函数调用也有两个性能"惩罚&#34 ;: *间接函数调用(PLT) *没有内林 M' m比较python性能和#34;静态链接的python" (Debian / Ubuntu Choice:Don' t使用./configure -enable-shared,python与libpython链接到"动态链接的python" (Fedora Choice:使用" ./配置 - 即可共享",python与libpython动态链接)。 使用-fno-semantic-Interthition,函数调用是直接的,可以在适当时内联。你不得不相信我,看看曲折地相容性基准结果;-) 使用时./configure - 即,共享(libpython)," python"二进制正是一个函数调用,并且' s全部: int main(int argc,char ** argv) {返回py_bytesmain(Argc,Argv); } 所以100%的时间只是在libpython中度过。 对于更长的理由,请参阅已接受的Fedora变更: https://fedoraproject.org/wiki/changes/pythonnosemanticintepositionspeedup.

也许我们需要提供一种方法来*从-fno-indantic-Interstinapition中选择退出*。例如,./configure - interthition。默认值是 - interposition。

我已经看到使用LD_PRELOAD的人来分开一些可以将实际呼叫修改为libpython的审计函数,或者插入一些功能的更快版本或收集指标(尽管有更好的方式)。 如果我们默认执行此操作,则一旦函数将被联合起来,这些用例将被打破。

>如果我们默认执行此操作,则一旦函数将被联合起来,这些用例将被打破。 这些用户是否可以使用A" ./配置 - 互相 - interthation-enable-shared"建造?

>这些用户是否可以使用A" ./配置 - 互相 - interthation-enable-shared"建造? 当然,但问题是默认值,没有? 也许它应该只在使用时默认 - 优化时

>也许它应该只在使用时默认 - 优化时 我认为它将增加 - 可优化标志的复杂性已经意味着PGO和LTO。 也许选择退出旗帜会更好的恕我直言。

>我认为它将增加 - 可优化标志的复杂性已经意味着PGO和LTO。 这就是为什么我建议它: - 为我的优化意味着"激活你可以更快地制作python的一切"

只是为了一个快速的DataPoint:llvm / clang默认情况下执行此操作,并且您需要一个显式`--fsemantic-interthition`来禁用它http://lists.llvm.org/pipermail/llvm-dev/2016-november/107625.html 在我看来,这里的性能提升真的突出了LD_PRELOAD的任何奇怪用法。

>在我看来,这里的性能提升真的突出了LD_PRELOAD的任何奇怪用法。 我非常确信这个断言,但其他用户不能,我认为讨论是如何以不太侵入的方式提供/激活选项,而不会破坏太多用例。 要诚实,我认为用户以这种方式使用LD_PRELOAD会非常罕见,所以如果我们默认激活它,我很好。但我仍然认为讨论这些案件并考虑他们会很好:)

在Malloc的情况下,每个内存分配代码都需要使用malloc / calloc / realloc。这是官方的,也是分配内存的唯一方法。但我们不保证Python Core只使用像Pyerr_occurred()这样的公共C API。它可以在内部使用更多的低级和高效但更少的更安全的C API。它可以用宏直接访问内部结构的函数(仅用于编译核心)。这实际上是这种情况。 overridding公共C API功能并不总是对核心产生影响。 所以我认为添加-fno-indante-intertheion可能不会破坏前面没有破坏的许多东西。 但是应该在Python-dev上讨论这一点。我相信一些C API函数被覆盖被覆盖。

>在Malloc的情况下,每个内存分配代码都需要使用malloc / calloc / realloc。这是官方的,也是分配内存的唯一方法。但我们不保证Python Core只使用像Pyerr_occurred()这样的公共C API。它可以在内部使用更多的低级和高效但更少的更安全的C API。它可以用宏直接访问内部结构的函数(仅用于编译核心)。这实际上是这种情况。 overridding公共C API功能并不总是对核心产生影响。 要确认您所说的内容:如果我们参加Pyerr_occurred()的具体示例,我最近添加了一个新的_pyerr_occurred()函数,被声明为静态内联函数。 _pyerr_occurred()不能覆盖。 静态内联PyObject * _pyerr_occurred(pythreadstate * tstate) { 断言(tstate!= null); 返回tstate-> curexc_type; }

Pablo: >我已经看到了使用LD_PRELOAD(...)的人来插入一些功能的更快版本或收集指标(尽管有更好的方式)。 恕我直言,如果有人必须进入"黑客和#34; Python,他们应该用特定选项重新编译Python。我不确定使用ld_preoad来获取"一些功能的更快版本"是性能期限的最佳方法,但我希望它方便:-) 查尔马拉帕斯: >我认为它将增加 - 可优化标志的复杂性已经意味着PGO和LTO。 它并没有启用lto,只有pgo :-)我们必须因为去年多个编译器错误而禁用lto。 Serhiy: >我相信一些C API函数被覆盖被覆盖。 它是一个理论用例,或者您是否知道当前在野外使用的这种用例? Ammar Askar: >只是为了一个快速的DataPoint:llvm / clang默认情况下执行此操作,并且您需要一个显式`--fsemantic-interthition`来禁用它http://lists.llvm.org/pipermail/llvm-dev/2016-november/107625.html 哦,那'非常有趣,谢谢!

我们写了一篇关于-Fno-Semantic-Inter关节标志的文章,我们在Rhel8和Fedora上使用GCC: https://developers.redhat.com/blog/2020/06/25/lred-hat-enterprise-linux-8-2-2-faster-python-3-8-run-speeds/ "启用此标志禁用语义插入,这可以将运行速度提高到30%。" 简而言之,该标志允许编译器在线代码,因此在用-Enable共享的Python构建Python时,请进一步优化。

是的,这应该成为--With-使用(a)支持它的平台上的优化的一部分 - (a)支持它和(b)它的重要信息。 如果这仅是 - 即可共享的构建(不是默认值),则我也可以在此处进行条件。 我从不使用 - 即可共享自己建立。

并回应其他人:不要担心LD_PRELOAD用户尝试覆盖内部。这不是一个支持的用例。它总是一个黑客。任何使用它都知道这一点。

嘿victor,我们应该在Python 3.10中试图将其降落吗? 鉴于除了基于LD_PRELOAD的黑客以及CLANG已经使这一点提出了任何重大关注,以及默认情况下,我认为它' s比较安全地为默认提供默认值。

Victor在假期持续了几个星期,所以我正在创造一个推动这一推动的PR。

新的Changeset b451b0e9a772f009f4161f7a46476190d0d17ac1 by Pablo Galindo在分支机构' master&#39 ;: bpo-38980:在用优化构建时添加-fno-semante interthition(gh-22862)https://github.com/python/cpython/commit / b451b0e9a772f009f4161f7a46476190d0d17ac1

我太渴望审查这一点:( 事实证明 - FNO-Semantic-Interthition`是GCC 5.3,所以[旧版GCC上的Builds失败](https://buildbot.python.org/all/#/builders/96/builds/216)。 我在研究如何在AutoTools中进行这种条件,我'

由彼得Viktorin新变更c6d7e82d19c091af698d4e4b3623648e259843e3分支'主&#39 ;: BPO-38980:仅适用-fno语意介入(如果可用)(GH-22892)https://github.com/python/cpython/commit/ C6D7E82D19C091AF698D4E4B3623648E259843E3

自Fedora和Rhel与-fno-semantic-Interthition构建Python以来,我们没有收到有关LD_PRELOAD用例的任何用户错误报告。 IMO我们可以安全地考虑没有用户依赖LD_PRELOAD来覆盖libpython符号。 感谢您实现Pablo和Petr的特征!