Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >跟Google学写代码--Chromium/base--cpu源码学习及应用

跟Google学写代码--Chromium/base--cpu源码学习及应用

作者头像
程序员的酒和故事
发布于 2018-03-12 09:15:23
发布于 2018-03-12 09:15:23
1K00
代码可运行
举报
运行总次数:0
代码可运行

Chromium是一个伟大的、庞大的开源工程,很多值得我们学习的地方。 前面写道: 《跟Google学写代码–Chromium/base–stl_util源码学习及应用》

《跟Google学写代码–Chromium/base–windows_version源码学习及应用》

今天分享cpu相关的操作。

先看看这个枚举:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  enum IntelMicroArchitecture {
    PENTIUM,
    SSE,
    SSE2,
    SSE3,
    SSSE3,
    SSE41,
    SSE42,
    AVX,
    MAX_INTEL_MICRO_ARCHITECTURE
  };

什么是sse? SSE(Streaming SIMD Extensions)是英特尔在AMD的3D Now!发布一年之后,在其计算机芯片Pentium III中引入的指令集,是MMX的超集。

SSE2 SSE2是Intel在Pentium 4处理器的最初版本中引入的,但是AMD后来在Opteron 和Athlon 64处理器中也加入了SSE2的支持。SSE2指令集添加了对64位双精度浮点数的支持。这个指令集还增加了对CPU快取的控制指令。AMD对它的扩展增加了8个XMM寄存器,但是需要切换到64位模式(AMD64)才可以使用这些寄存器。

SSE3 SSE3是Intel在Pentium 4处理器的 Prescott 核心中引入的第三代SIMD指令集,AMD在Athlon 64的第五个版本,Venice核心中也加入了SSE3的支持。以及对超执行绪技术的支持。 SSSE3 SSSE3是Intel针对SSE3指令集的一次额外扩充,最早内建于Core 2 Duo处理器中。

SSE4 SSE4是Intel在Penryn核心的Core 2 Duo与Core 2 Solo处理器时,新增的47条新多媒体指令集,多媒体指令集,并内建在Phenom与Opteron等K10架构处理器中,不过无法与Intel的SSE4系列指令集相容。

SSE5 SSE5]是AMD为了打破Intel垄断在处理器指令集的独霸地位所提出的,SSE5初期规划将加入超过100条新指令,其中最引人注目的就是三算子指令(3-Operand Instructions)及熔合乘法累积(Fused Multiply Accumulate)。其中,三算子指令让处理器可将一个数学或逻辑函式库,套用到算子或输入资料。借由增加算子的数量,一个 x86 指令能处理二至三笔资料, SSE5 允许将多个简单指令汇整成一个指令,达到更有效率的指令处理模式。提升为三运算指令的运算能力,是少数 RISC 架构的水平。熔合乘法累积让允许建立新的指令,有效率地执行各种复杂的运算。熔合乘法累积可结合乘法与加法运算,透过单一指令执行多笔重复计算。透过简化程式码,让系统能迅速执行绘图着色、快速相片着色、音场音效,以及复杂向量演算等效能密集的应用作业。SSE5最快将内建于AMD下一代Bulldozer核心。

AVX AVX是Intel的SSE延伸架构,如IA16至IA32般的把暂存器XMM 128bit提升至YMM 256bit,以增加一倍的运算效率。此架构支持了三运算指令(3-Operand Instructions),减少在编码上需要先复制才能运算的动作。在微码部分使用了LES LDS这两少用的指令作为延伸指令Prefix。

cpu.h 由于这个类比较简短,所以就贴上所有的头文件了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#ifndef BASE_CPU_H_#define BASE_CPU_H_#include <string>#include "base/base_export.h"namespace base {// Query information about the processor.class BASE_EXPORT CPU { public:  // Constructor
  CPU();  enum IntelMicroArchitecture {
    PENTIUM,
    SSE,
    SSE2,
    SSE3,
    SSSE3,
    SSE41,
    SSE42,
    AVX,
    MAX_INTEL_MICRO_ARCHITECTURE
  };  // Accessors for CPU information.
  const std::string& vendor_name() const { return cpu_vendor_; }  int signature() const { return signature_; }  int stepping() const { return stepping_; }  int model() const { return model_; }  int family() const { return family_; }  int type() const { return type_; }  int extended_model() const { return ext_model_; }  int extended_family() const { return ext_family_; }  bool has_mmx() const { return has_mmx_; }  bool has_sse() const { return has_sse_; }  bool has_sse2() const { return has_sse2_; }  bool has_sse3() const { return has_sse3_; }  bool has_ssse3() const { return has_ssse3_; }  bool has_sse41() const { return has_sse41_; }  bool has_sse42() const { return has_sse42_; }  bool has_avx() const { return has_avx_; }  // has_avx_hardware returns true when AVX is present in the CPU. This might
  // differ from the value of |has_avx()| because |has_avx()| also tests for
  // operating system support needed to actually call AVX instuctions.
  // Note: you should never need to call this function. It was added in order
  // to workaround a bug in NSS but |has_avx()| is what you want.
  bool has_avx_hardware() const { return has_avx_hardware_; }  bool has_aesni() const { return has_aesni_; }  bool has_non_stop_time_stamp_counter() const {    return has_non_stop_time_stamp_counter_;
  }  // has_broken_neon is only valid on ARM chips. If true, it indicates that we
  // believe that the NEON unit on the current CPU is flawed and cannot execute
  // some code. See https://code.google.com/p/chromium/issues/detail?id=341598
  bool has_broken_neon() const { return has_broken_neon_; }

  IntelMicroArchitecture GetIntelMicroArchitecture() const;  const std::string& cpu_brand() const { return cpu_brand_; } private:  // Query the processor for CPUID information.
  void Initialize();  int signature_;  // raw form of type, family, model, and stepping
  int type_;  // process type
  int family_;  // family of the processor
  int model_;  // model of processor
  int stepping_;  // processor revision number
  int ext_model_;  int ext_family_;  bool has_mmx_;  bool has_sse_;  bool has_sse2_;  bool has_sse3_;  bool has_ssse3_;  bool has_sse41_;  bool has_sse42_;  bool has_avx_;  bool has_avx_hardware_;  bool has_aesni_;  bool has_non_stop_time_stamp_counter_;  bool has_broken_neon_;  std::string cpu_vendor_;  std::string cpu_brand_;
};

}  // namespace base#endif  // BASE_CPU_H_

Initialize的实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void CPU::Initialize() {#if defined(ARCH_CPU_X86_FAMILY)
  int cpu_info[4] = {-1};  char cpu_string[48];  // __cpuid with an InfoType argument of 0 returns the number of
  // valid Ids in CPUInfo[0] and the CPU identification string in
  // the other three array elements. The CPU identification string is
  // not in linear order. The code below arranges the information
  // in a human readable form. The human readable order is CPUInfo[1] |
  // CPUInfo[3] | CPUInfo[2]. CPUInfo[2] and CPUInfo[3] are swapped
  // before using memcpy to copy these three array elements to cpu_string.
  __cpuid(cpu_info, 0);  int num_ids = cpu_info[0];  std::swap(cpu_info[2], cpu_info[3]);  memcpy(cpu_string, &cpu_info[1], 3 * sizeof(cpu_info[1]));
  cpu_vendor_.assign(cpu_string, 3 * sizeof(cpu_info[1]));  // Interpret CPU feature information.
  if (num_ids > 0) {
    __cpuid(cpu_info, 1);
    signature_ = cpu_info[0];
    stepping_ = cpu_info[0] & 0xf;
    model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0);
    family_ = (cpu_info[0] >> 8) & 0xf;
    type_ = (cpu_info[0] >> 12) & 0x3;
    ext_model_ = (cpu_info[0] >> 16) & 0xf;
    ext_family_ = (cpu_info[0] >> 20) & 0xff;
    has_mmx_ =   (cpu_info[3] & 0x00800000) != 0;
    has_sse_ =   (cpu_info[3] & 0x02000000) != 0;
    has_sse2_ =  (cpu_info[3] & 0x04000000) != 0;
    has_sse3_ =  (cpu_info[2] & 0x00000001) != 0;
    has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
    has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
    has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
    has_avx_hardware_ =
                 (cpu_info[2] & 0x10000000) != 0;    // AVX instructions will generate an illegal instruction exception unless
    //   a) they are supported by the CPU,
    //   b) XSAVE is supported by the CPU and
    //   c) XSAVE is enabled by the kernel.
    // See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
    //
    // In addition, we have observed some crashes with the xgetbv instruction
    // even after following Intel's example code. (See crbug.com/375968.)
    // Because of that, we also test the XSAVE bit because its description in
    // the CPUID documentation suggests that it signals xgetbv support.
    has_avx_ =
        has_avx_hardware_ &&
        (cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
        (cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
        (_xgetbv(0) & 6) == 6 /* XSAVE enabled by kernel */;
    has_aesni_ = (cpu_info[2] & 0x02000000) != 0;
  }  // Get the brand string of the cpu.
  __cpuid(cpu_info, 0x80000000);  const int parameter_end = 0x80000004;  int max_parameter = cpu_info[0];  if (cpu_info[0] >= parameter_end) {    char* cpu_string_ptr = cpu_string;    for (int parameter = 0x80000002; parameter <= parameter_end &&
         cpu_string_ptr < &cpu_string[sizeof(cpu_string)]; parameter++) {
      __cpuid(cpu_info, parameter);      memcpy(cpu_string_ptr, cpu_info, sizeof(cpu_info));
      cpu_string_ptr += sizeof(cpu_info);
    }
    cpu_brand_.assign(cpu_string, cpu_string_ptr - cpu_string);
  }  const int parameter_containing_non_stop_time_stamp_counter = 0x80000007;  if (max_parameter >= parameter_containing_non_stop_time_stamp_counter) {
    __cpuid(cpu_info, parameter_containing_non_stop_time_stamp_counter);
    has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0;
  }#elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
  cpu_brand_.assign(g_lazy_cpuinfo.Get().brand());
  has_broken_neon_ = g_lazy_cpuinfo.Get().has_broken_neon();#endif}

CPU::IntelMicroArchitecture CPU::GetIntelMicroArchitecture() const {  if (has_avx()) return AVX;  if (has_sse42()) return SSE42;  if (has_sse41()) return SSE41;  if (has_ssse3()) return SSSE3;  if (has_sse3()) return SSE3;  if (has_sse2()) return SSE2;  if (has_sse()) return SSE;  return PENTIUM;
}

上面的代码中用到了__cpuid,下面就行介绍介绍。

__cpuid

功能: Generates the cpuid instruction available on x86 and x64, which queries the processor for information about the supported features and CPU type.

原型:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void __cpuid(   int CPUInfo[4],   int InfoType
);

更多请关注: https://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx

__cpuidex函数的InfoType参数是CPUID指令的eax参数,即功能ID。ECXValue参数是CPUID指令的ecx参数,即子功能ID。CPUInfo参数用于接收输出的eax, ebx, ecx, edx这四个寄存器。

用条件编译判断VC编译器对Intrinsics函数的支持性(_MSC_VER)。

使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main(int argc, char* argv[]) {

  base::CPU *cpu = new base::CPU();  std::cout << cpu->cpu_brand() << std::endl;
  system("pause");  return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 人生有味是多巴胺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
如何检测处理器是否支持AES-NI指令集?
本文介绍如何检测处理器是否支持AES-NI指令集,首先我们先了解一下什么是AES-NI指令集。
隔壁没老王
2020/03/03
9.9K0
如何检测处理器是否支持AES-NI指令集?
【Linux 内核 内存管理】Linux 内核内存布局 ① ( 查看 Linux 操作系统位数 | 查看 Linux 操作系统软硬件信息 )
命令 , 可以查看 " Linux 内核位数 “ 和 ” 系统的软硬件信息 " ;
韩曙亮
2023/03/30
32.4K0
【Linux 内核 内存管理】Linux 内核内存布局 ① ( 查看 Linux 操作系统位数 | 查看 Linux 操作系统软硬件信息 )
NumPy 1.26 中文文档(四十九)
多年来,NumPy 为第三方扩展暴露的 API 已发展壮大,并使程序员能够直接从 C 中访问 NumPy 功能。这个 API 最好被描述为“有机的”。它是由多种竞争性的愿望和多种观点多年形成的,受到希望使用户能够从 Numeric 和 Numarray 迁移到 NumPy 方面的强烈影响。核心 API 始于 1995 年的 Numeric,并有一些模式,比如大量使用宏来模仿 Python 的 C-API 以及适应 90 年代晚期的编译器技术。只有一小群志愿者很少有时间投入到改进这个 API 上。
ApacheCN_飞龙
2024/07/01
3750
NumPy 1.26 中文文档(四十九)
Linux 获取cpu信息
本文记录Linux系统获取CPU信息方法。 命令 1 cat /proc/cpuinfo 得到输出信息: processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 63 model name : Intel(R) Xeon(R) CPU E5-2678 v3 @ 2.50GHz stepping : 2 microcode : 0x43 cpu MHz : 1200.000 cache size : 30720 KB p
为为为什么
2022/08/05
9.1K0
`proccpuinfo` 文件中最常见的标志
/proc/cpuinfo 是一个虚拟文件系统,在 Linux 系统中提供有关 CPU(中央处理器)的信息。通过读取该文件,您可以获取有关处理器的详细信息,如型号、频率、核心数、缓存大小等。本文将介绍 /proc/cpuinfo 文件中最常见的标志,并提供相应的示例。
网络技术联盟站
2023/06/08
7300
`proccpuinfo` 文件中最常见的标志
小白Linux入门--入门篇(四):查看Linux版本信息
很多时候,我们需要下载软件的时候,必须要知道我们使用的Linux系统是什么版本,32还是64位等等,可以使用最简单的命令查看:uname -a
浩Coding
2019/07/02
1.8K0
小白Linux入门--入门篇(四):查看Linux版本信息
查看linux系统版本命令汇总
Linux下如何查看版本信息, 包括位数、版本信息以及CPU内核信息、CPU具体型号等等,整个CPU信息一目了然。 1、Linux查看版本当前操作系统内核信息   命令:uname -a 2、Li
架构师专栏
2018/06/29
4.4K0
Linux如何查看CPU信息,Linux查看CPU个数和核心数,Linux查看CPU使用率和运行位数
2017年11月24日 11:52:17 tiiefu1212 阅读数 14584
拓荒者
2019/08/29
64.2K0
Linux如何查看CPU信息,Linux查看CPU个数和核心数,Linux查看CPU使用率和运行位数
Linux的sysctl命令
有时候我们需要在终端下查看系统的相关信息,就需要用到sysctl命令,例如我的电脑是Mac,我要查看CPU的相关信息,命令和输出结果如下:
Tyan
2019/05/25
1.1K0
KVM基础1
KVM (Kernel-based Virtual Machine) 是基于 虚拟化扩展指令集 (Intel VT or AMD-V) 在 linux x86 平台上的 完全虚拟化 解决方案
franket
2021/12/03
5570
KVM基础
KVM (Kernel-based Virtual Machine) 是基于 虚拟化扩展指令集 (Intel VT or AMD-V) 在 linux x86 平台上的 完全虚拟化 解决方案
franket
2022/01/19
1.3K0
浅析Clickhouse的向量化执行
关于Clickhouse之所以会像闪电一样快,是多方面的优化,包过但不仅限于:高效且磁盘友好的列式存储,高效的数据压缩,精心设计的各类索引,并行分布式查询,运行时代码生成等。
公众号-利志分享
2022/04/25
6700
基于 AlmaLinux 9 安装 GitLab 社区版实战
本文是一个系列,本篇为系列文章的第一篇:基于 AlmaLinux 9 安装 GitLab 社区版实战
远哥制造
2024/11/02
2600
基于 AlmaLinux 9 安装 GitLab 社区版实战
java高级用法之:绑定CPU的线程Thread-Affinity
在现代计算机系统中,可以有多个CPU,每个CPU又可以有多核。为了充分利用现代CPU的功能,JAVA中引入了多线程,不同的线程可以同时在不同CPU或者不同CPU核中运行。但是对于JAVA程序猿来说创建多少线程是可以自己控制的,但是线程到底运行在哪个CPU上,则是一个黑盒子,一般来说很难得知。
程序那些事
2022/05/11
1.1K0
如何查看linux系统内核版本_centos7内核版本
该命令适用于所有Linux系统,会显示出完整的版本信息,包括Linux系统的名称,如Debian、Ubuntu、CentOS等,和对应的版本号,以及该版本的代号,例如在Debian 8中将会显示代号jessie。
全栈程序员站长
2022/09/25
7.6K0
[强基固本-视频压缩]第十二章:向量指令 第一部分
向量计算是在执行单个处理器指令时,对多个数据块同时执行相同类型的多个操作。这一原理也被称为 SIMD(单指令多数据)。这个名字源于与向量代数的明显相似性:向量之间的操作具有单一符号表示,但涉及对向量各分量执行多个算术操作。
用户1324186
2024/03/20
2940
[强基固本-视频压缩]第十二章:向量指令 第一部分
运维人员常用的Linux命令总结
cpu相关信息存放在/proc/cpuinfo目录中,所以要查看cpu信息就可以用以下命令:
职场亮哥
2020/10/10
1.7K0
运维人员常用的Linux命令总结
DPDK 21.11.1版本的交叉编译
在DPDK使用meson管理后相对之前的编译方法已经变的简单和清晰了,为此我们简单介绍一下如何进行給21.11.1版本的交叉编译,如果对如何编译DPDK没有概念请参考:
通信行业搬砖工
2023/10/09
8540
DPDK 21.11.1版本的交叉编译
Linux CPU与内存常见问题处理技巧
可以通过Linux执行lscpu命令,输出信息Flags部分即是支持的指令集列表。
Power
2025/02/28
1600
Linux 命令(146) —— lscpu 命令
lscpu 从伪文件系统(sysfs)、/proc/cpuinfo 和任何可用的特定体系架构库(如 Powerpc 上的 librtas)收集 CPU 架构信息。命令输出可读,也可用于分析。输出内容包括:CPU、线程、内核的数量,以及非统一存储器存取(NUMA)节点。此外还包括关于 CPU 高速缓存和高速缓存共享的信息,家族、模型、bogoMIPS、字节顺序和步进(stepping)。
恋喵大鲤鱼
2022/10/24
8.7K0
相关推荐
如何检测处理器是否支持AES-NI指令集?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验