Tensorflow(libtensorflow)报指令集与处理惩罚器不兼容

打印 上一主题 下一主题

主题 660|帖子 660|积分 1980

迩来连续在多个项目上接收到Tensorflow与环境不兼容题目的报告。
  主要现象

  

  • 在一个新部署大概升级的环境上,服务尝试启动;
  

  • 正常实行过程中,服务加载模型,标准错误中输出一行错误信息后服务制止。
  错误信息:
  <blockquote class="kdocs-blockquote" style="text-align:left;">   tensorflow/core/platform/cpu_feature_guard.cc:36] The TensorFlow library was compiled to use SSE4.1 instructions, but these aren't available on your machine    目前至少有三个出现错误的呆板,CPU分别为:
  

  • Intel Xeon E5 4640
  

  • AMD Opteron 6376
  

  • Intel Xeon Gold 6130
  可是,根据Intel和AMD的硬件信息,以上CPU都已经支持 SSE4.1,但TensorFlow都提示不支持,因此不是硬件不符合要求造成的。那题目出在哪里呢?
  题目排查

  首先,肯定是确认Tensorflow的检测自己是否有题目。
  首先根据代码提示查看了Tensorflow源代码。查抄CPU指令集支持的代码位于tensorflow / core / platform /cpu_info.cc 中Initialize()方法。
  1.     // To getgeneral information and extended features we send eax = 1 and
  2.     // ecx = 0 tocpuid. The response is returned in eax,ebx, ecx and edx.
  3.     // (See Intel 64and IA-32 Architectures Software Developer's Manual
  4.     // Volume 2A:Instruction Set Reference, A-M CPUID).
  5.     GETCPUID(eax, ebx, ecx, edx, 1, 0);
  6.   
  7.     cpuid->model_num_ = static_cast<int>((eax >> 4) & 0xf);
  8.     cpuid->family_ = static_cast<int>((eax >> 8) & 0xf);
复制代码
…….
  1.     cpuid->have_sse2_ = (edx >> 26) & 0x1;
  2.     cpuid->have_sse3_ = ecx & 0x1;
  3.     cpuid->have_sse4_1_ = (ecx >> 19) & 0x1;
  4.     cpuid->have_sse4_2_ = (ecx >> 20) & 0x1;
  5.     cpuid->have_sse_ = (edx >> 25) & 0x1;
  6.     cpuid->have_ssse3_ = (ecx >> 9) & 0x1;
  7.     cpuid->have_hypervisor_ = (ecx >> 31) & 1;
复制代码
其中,GETCPUID(a, b, c,d, eax, ecx)是用gcc汇编实现的:
  1. #define GETCPUID(a, b, c, d, a_inp, c_inp) \
  2.   asm("mov %%rbx, %%rdi\n"                 \
  3.       "cpuid\n"                            \
  4.       "xchg %%rdi, %%rbx\n"                \
  5.       : "=a"(a), "=D"(b), "=c"(c), "=d"(d) \
  6.       : "a"(a_inp), "2"(c_inp))
  7. #endif
复制代码
从Tensorflow的代码上看是使用CPUID指令获取CPU信息的,假如是在真实装备上实行的话,这样没有题目。
  然后,我查抄了cpuinfo。
  根据查抄,这些环境cpuinfo的flags都没有SSE4.1,因此有须要研究cpuinfo的信息生成方式。
  Stack Overflow上面的这个题目介绍了Linux内核获取CPU信息的方法。Linux内核也使用CPUID指令获取CPU信息,
  通过查看Linux x86源码,在arch/x86/kernel/cpu/proc.c 中,flags 是按如下方式生成的。
  1.     seq_printf(m,"flags\t\t:");
  2.     for (i = 0; i < 32*NCAPINTS;i++)
  3.        if (cpu_has(c, i) && x86_cap_flags[i] !=NULL)
  4.            seq_printf(m, " %s", x86_cap_flags[i]);
复制代码
以上代码表明,Linux内核也使用CPUID指令获取CPU信息,但是对自己不明白的CPUID信息不会显示在 flags中,即CPUID不显示不表示该指令集不可用,可能只是内核没有支持。
  题目排查的远景突然暗淡了下来。
  这时间,我又再次查抄了cpuinfo。突然有个发现,目前所有出现题目的呆板均运行于假造机上(cpuinfo flags上 有 hypervisor 标识),根据上述排查可以推断,假造机假造的CPU存在题目。
  在查找资料,我看到了以下两条信息:
  首先是linux下面最广泛使用的qemu-kvm,大名鼎鼎的OpenStack底层也是它。在Linux-KVM 以及实现层qemu-kvm中,CPU模型(models)界说了哪些主机的CPU功能(features)会被暴露给客户机操纵体系。为了在具有差别 CPU 功能的主机之间做安全的迁移,qemu-kvm往往不会将主机CPU的所有功能都暴露给客户机。可以使用-cpu (model),(feature) 指定模仿的CPU特性,也可以直接使用 -cpu host,这样的话会客户机使用和主机雷同的 CPU model。
  详细的设置可以参考:https://qemu.weilnetz.de/doc/4.2/qemu-doc.html#cpu_005fmodels
  其次是VMWare家。在VMWare vCenter中,EVC答应在差别代的CPU之间迁移假造机,位于EVC集群中的CPU功能是受到限制的,其中Intel “Merom” Generation (Intel Xeon Core 2) / AMD Opteron Generation 3(以及更早版本)不支持SSE4.1。
  详细的信息可以参考:https://kb.vmware.com/s/article/1005764
  于是我尝试联系了其中一个客户。
  客户生产环境使用H3C CAS假造化平台。H3C CAS平台创建假造机时可以选择CPU模仿方式,其中Custom模式不支持AES指令集,理论上也不支持邻近的SSE4.1指令集。但是通过修改设置,将CPU改为pass-through可以支持。
  于是我们让客户停机,做了修改。题目办理。
  结论

  最后,我们在部署环境要求上增加了如下的CPU要求:
  假如该服务器运行于假造机上,则要求QEMU体系的假造机下(如OpenStack、H3C CAS及其他基于KMV的定制化云平台等环境),必须确认假造机CPU工作模式设置为“定制化模式”或“穿透模式”。
  同时我们也编译了仅支持sse3的libtensorflow。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万有斥力

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表