【问题标题】:Docker and -march nativeDocker 和 -march 原生
【发布时间】:2019-11-01 13:44:07
【问题描述】:

我的应用程序极大地受益于 gcc 在使用 -march native 运行时可以访问的高级 CPU 功能。 Docker 可以平滑操作系统的差异,但它如何处理不同的 CPU?要构建一个可以在任何 CPU 上运行的应用程序,我必须为 amd64 构建,这会损失很多性能。当需要为每个 CPU 架构单独编译应用程序时,有没有好的方法来分发 Docker 镜像?

【问题讨论】:

  • 解决这个问题的一个通用方法是构建多个版本并在运行时选择最好的一个。 (例如,使用帮助脚本)。或者,如果您的代码是一个动态库,使用动态库技巧将函数指针解析为运行它的 CPU 的版本。但是,如果您的程序不是共享库,并且您不希望程序内部运行时调度开销,那么可以构建多个版本并选择一个与脚本或 CPU 检测包装程序一起运行是一种方法。 (例如,运行 cpuid 的 C 或 asm 程序,或解析 /proc/cpuinfo 的 shell 脚本)

标签: docker gcc x86-64 cpu-architecture avx


【解决方案1】:

Docker 根本不处理 CPU。它只是kernel namespacing、FS 系统分层(例如UnionFS)和process quoting 的组合。
当您在 docker 容器上运行某些东西时,它只是在您的操作系统上运行的可执行文件,没有虚拟化,它只能访问一组选定的内核对象(例如设备)并且它被 chroot 到一个 FS 层次结构,该层次结构是由覆盖不同的 FS(包括 docker 容器中的那个)产生的。

因此,Docker 根本不处理 CPU,它与您的问题完全正交。

作为Peter commented,CPU调度基本上有两种方式:

  1. 您加载了正确的动态库(但对库的每个函数调用都使用一个指针)。
  2. 您构建同一个静态链接二进制文件的多个版本并运行正确的版本。

主要问题是有时 ISA 扩展是正交的,这使得组合(即库/二进制文件的数量)呈指数增长。 因此,考虑到您正在处理 Docker 的用户群,您可以稍微简化一下方法(如果组合存在问题):

  1. 要么需要一些 ISA 扩展(如果缺少这些扩展会过多地降低性能)。对于可选扩展,您可以使用上述方法之一。
  2. 只创建几个基线容器。例如。一种用于通用amd64,一种用于amd64-avx,一种用于amd64-avx2-aesni-tsx 和类似的。这个想法是只创建几个容器,覆盖所有大多数少数用户。

编辑
正如BeeOnRope pointed in the comments,Dockers 一个在 Windows 上运行的版本。 It uses Hyper-V to run a Linux VM with the Linux version of docker.
由于 Hyper-V 是本机 VMM,除了额外的层外,同样的注意事项也适用。
同样,也有一个 macOS 版本。 This time it uses an hypervisor framework based on xhyve.

【讨论】:

  • 好答案!可能值得注意的是,在 Linux-on-Linux 以外的任何情况下(使用表示法 guest-on-host),VM is 使用。所以 Docker 在 L-on-L 场景之外实际上是一种完全不同的技术(但我怀疑 VM 会模拟主机不支持的指令)。
  • @BeeOnRope 好点!我完全不知道 Docker for Windows。谢谢,我会将其编辑为答案。
  • OSX 也有 docker。就纯场景而言,L-on-L属于mintority,虽然就实际使用而言,我不确定。
  • 我并不是在建议静态链接的二进制文件。但可以肯定的是,如果您遇到可执行 库都受益于使用-march=whatever 编译的情况,那么静态链接可能是一个很好的方法。使用 Docker,您可能不会失去与其他任务共享库只读页面的机会,因为 docker 映像中的 libc 是一个单独的文件,而不是另一个 docker 映像中的 libc,或者主持人。 (我认为?)当然对于自定义库。
猜你喜欢
  • 2019-05-31
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 2023-03-19
  • 2017-07-31
  • 2011-05-27
  • 2011-01-18
相关资源
最近更新 更多