【问题标题】:Disabling Compiler Optimizations when Building CPython在构建 CPython 时禁用编译器优化
【发布时间】:2019-01-19 04:51:13
【问题描述】:

我一直在关注 Philip Guo 的 excellent series 关于 CPython 的内部结构,并一直在使用 GDB 浏览解释器的代码。不幸的是,当我单步执行代码时,GDB 似乎跳过了很多,乱序执行指令(例如一系列赋值操作,没什么特别的)。

据我了解,这是因为编译器优化。事实上,CPython 的configure 文件似乎默认为-O2。使用./configuremake 编译Python 2.7.15 时就是这种情况:

gcc -pthread -c -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Modules/python.o ./Modules/python.c
gcc -pthread -c -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/acceler.o Parser/acceler.c
gcc -pthread -c -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/grammar1.o Parser/grammar1.c
gcc -pthread -c -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/listnode.o Parser/listnode.c
...

我尝试通过./configure CFLAGS="-g -O0" 配置不优化并再次使用make 编译来解决此问题(注意每行从-fno-strict-aliasing -g -O2-fno-strict-aliasing -g -O0 的更改):

gcc -pthread -c -fno-strict-aliasing -g -O0 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Modules/python.o ./Modules/python.c
gcc -pthread -c -fno-strict-aliasing -g -O0 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/acceler.o Parser/acceler.c
gcc -pthread -c -fno-strict-aliasing -g -O0 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/grammar1.o Parser/grammar1.c
gcc -pthread -c -fno-strict-aliasing -g -O0 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes  -I. -IInclude -I./Include   -DPy_BUILD_CORE -o Parser/listnode.o Parser/listnode.c
...

不幸的是,当我单步执行代码时,GDB 仍然会跳来跳去。为了完整起见,这是我使用 GDB 运行的命令:

gdb --args ./python test.py

test.py 的内容只是一些基本的算术和打印函数,并不真正相关。

我对其中至少一个步骤的理解一定是不完整的。我是否错误地设置了优化标志? GDB 是否由于其他原因在指令之间跳转?任何建议将不胜感激。谢谢!

【问题讨论】:

    标签: python c makefile gdb


    【解决方案1】:

    tl;dr:你想要configure 设置--with-pydebug

    -O2 之后的命令行上有一个-O3,因此将-O2 更改为-O0 没有任何好处; -O3 仍然覆盖它。您需要弄清楚-O3 的来源并将其删除。

    如果您查看生成的Makefile,您应该会看到如下内容:

    # Compiler options
    OPT=        -DNDEBUG -g -fwrapv -O3 -Wall
    # ...
    # Avoid assigning CFLAGS, LDFLAGS, etc. so users can use them on the
    # command line to append to these values without stomping the pre-set
    # values.
    PY_CFLAGS=  $(BASECFLAGS) $(OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS)
    

    当然,您可以只编辑生成的Makefile,将-O3 更改为-O0。但是,如果您查看 configure 脚本和 Makefile.pre 内部,您可以看到它的来源:它是默认值,仅在这种情况下被替换:

    case $ac_cv_prog_cc_g in
    yes)
        if test "$Py_DEBUG" = 'true' ; then
        # Optimization messes up debuggers, so turn it off for
        # debug builds.
                if "$CC" -v --help 2>/dev/null |grep -- -Og > /dev/null; then
                    OPT="-g -Og -Wall"
                else
                    OPT="-g -O0 -Wall"
                fi
        else
        OPT="-g $WRAP -O3 -Wall"
        fi
        ;;
    

    这也为除了gcc之外的其他编译器设置了正确的标志。

    但是,--with-pydebug 的主要作用是启用 Py_DEBUG — 如果您正在调试 CPython 源代码,您可能需要它,但它与 -O0 是分开的,这是您实际要求的关于。所以,如果你想要-O0,据我所知,你唯一能做的就是编辑Makefile(或者想出一些复杂的环境变量集和configure诱使它进行调试构建但未启用 Py_DEBUG) 的参数。

    【讨论】:

    • 成功了,谢谢!我错过了--with-pydebug 禁用优化的事实。然而,一个好奇的是,使用--with-pydebugnot 使用CFLAGS="-g -O0",导致第一个-O2 仍然出现在命令行中。不过,第二个确实更改为-O0。知道为什么这仍然会整体禁用优化吗?
    • @jdtaylor7 你的 gcc 设置或 bash 配置文件或其他地方有默认的 CFLAGS 吗?
    • 我在.bashrc.profile.bash_profile 中没有任何默认值。我也没有设置任何 gcc 默认值,所以我不相信任何地方都有默认的CFLAGSecho $CFLAGS 也不返回任何内容。
    • @jdtaylor7 我假设您使用的是 Linux — 但什么发行版和版本?如果我有足够相似的 VM 可以尝试,我可以看看可能发生的情况。同时,原因是后面的 -O 标志会覆盖任何较早的标志,因此 -O0 -O3 表示 -O3 (为什么您的原始修复无法自行工作),但 -O2 -O0 表示 -O0 (为什么—with-pydebug 可以单独工作,也可以一起修复)。这在 gcc 文档中的某处进行了解释;以后有机会我可以查一下。
    • 没错,我在 Arch 上。不过,你现在已经回答了我所有的问题。从您的原始答案中,我的印象是命令行上存在的最高优化级别是最终使用的优化,但如果 gcc 使用最新的优化标志,那么这是完全有意义的。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 2011-08-11
    • 2010-11-15
    • 2013-08-30
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    相关资源
    最近更新 更多