cpu 订阅
中央处理器(CPU,central processing unit)作为计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元。CPU 自产生以来,在逻辑结构、运行效率以及功能外延上取得了巨大发展。 [1] 展开全文
中央处理器(CPU,central processing unit)作为计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元。CPU 自产生以来,在逻辑结构、运行效率以及功能外延上取得了巨大发展。 [1]
信息
运行工作
处理指令、执行操作、控制时间、处理数据
简    称
CPU
所属类别
计算机系统的执行单元
中文名
中央处理器
功    能
信息处理、程序运行的最终执行单元
外文名
central processing unit
中央处理器简介
中央处理器(CPU),是电子计算机的主要设备之一,电脑中的核心配件。其功能主要是解释计算机指令以及处理计算机软件中的数据。CPU是计算机中负责读取指令,对指令译码并执行指令的核心部件。中央处理器主要包括两个部分,即控制器、运算器,其中还包括高速缓冲存储器及实现它们之间联系的数据、控制的总线。电子计算机三大核心部件就是CPU、内部存储器、输入/输出设备。中央处理器的功效主要为处理指令、执行操作、控制时间、处理数据。 [2]  在计算机体系结构中,CPU 是对计算机的所有硬件资源(如存储器、输入输出单元) 进行控制调配、执行通用运算的核心硬件单元。CPU 是计算机的运算和控制核心。计算机系统中所有软件层的操作,最终都将通过指令集映射为CPU的操作。 [1] 
收起全文
精华内容
下载资源
问答
  • cpu
    千次阅读
    2022-04-02 22:03:03

    目录

    静态声明与定义

    申请动态per-CPU变量

    使用静态per-CPU变量

    使用一、CPU并行访问计数

    使用二、在软中断中唤醒

    使用三、静/动态per-CPU验证


     

     

    per_cpu机制就是让每个处理器都分配了该变量的副本,有自己的私有数据段,不需要考虑与其他它处理器的竞争的问题,该副本可以充分利用处理器本地的硬件缓冲cache来提供访问速度。

     

    per-CPU按照存储变量的空间来源分为

    • 静态per-CPU变量:存储空间是在代码编译时静态分配的
    • 动态per-CPU变量,存储空间是在代码的执行期间动态分配的

     

    静态声明与定义

    #define DECLARE_PER_CPU(type, name)                 \
        DECLARE_PER_CPU_SECTION(type, name, "")
    
    #define DECLARE_PER_CPU_SECTION(type, name, sec)            \
        extern __PCPU_ATTRS(sec) __typeof__(type) name
    
    #define __PCPU_ATTRS(sec)                       \
        __percpu __attribute__((section(PER_CPU_BASE_SECTION sec))) \
        PER_CPU_ATTRIBUTES

     

    申请动态per-CPU变量

    分配per-CPU变量

    #define alloc_percpu(type)                      \
        (typeof(type) __percpu *)__alloc_percpu(sizeof(type),       \
                            __alignof__(type))

    释放:

    void free_percpu(void __percpu *ptr)

     

    使用静态per-CPU变量

    #define get_cpu_var(var)                        \
    (*({                                    \
        preempt_disable();                      \
        this_cpu_ptr(&var);                     \
    }))
    
    #define put_cpu_var(var)                        \
    do {                                    \
        (void)&(var);                           \
        preempt_enable();                       \
    } while (0)

    使用一、CPU并行访问计数

    多线程中,每个CPU执行的次数

    long DriverIOControl( struct file *pslFileStruct, unsigned int uiCmd, unsigned long ulArg )
    {
        long *pUsage = NULL;
        /* printk( KERN_ALERT DEVICE_NAME ": pUsage = 0x%lx %lx %ld", (unsigned long) pUsage, (unsigned long) (&gUsage), (*pUsage) ); */
        preempt_disable();
        pUsage = this_cpu_ptr( (long *) (&gUsage) );
        (*pUsage)++;
        preempt_enable();
        return(0);
    }

     

    使用二、在软中断中唤醒

    softirq软中断源码,__this_cpu_read()

    static void wakeup_softirqd(void)
    {
    	/* Interrupts are disabled: no need to stop preemption */
    	struct task_struct *tsk = __this_cpu_read(ksoftirqd);
    
    	if (tsk && tsk->state != TASK_RUNNING)
    		wake_up_process(tsk);
    }
    

     

    使用三、静/动态per-CPU验证

    静态和动态变量的使用,遍历每个CPU的值

    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/percpu.h>
    #include <linux/cpumask.h>
    static DEFINE_PER_CPU(long, cpuvar) = 5;
    static long __percpu *cpualloc;
    
    static int __init my_init(void)
    {
        int cpu;
        pr_info("module loaded at 0x%p\n", my_init);
        /* modify the cpuvar value */
        for_each_possible_cpu(cpu)
        {
            per_cpu(cpuvar, cpu) = 10;
            pr_info("init: cpuvar on cpu%d = %ld\n",
                    cpu, get_cpu_var(cpuvar));
            put_cpu_var(cpuvar);
        }
        __this_cpu_write(cpuvar, 10);
        /* alloc a percpu value */
        cpualloc = alloc_percpu(long);
        /* set all cpu for this value */
        for_each_possible_cpu(cpu)
        {
            *per_cpu_ptr(cpualloc, cpu) = 666;
            pr_info("init: cpu:%d cpualloc = %ld\n",
                    cpu, *per_cpu_ptr(cpualloc, cpu));
        }
        return 0;
    }
    static void __exit my_exit(void)
    {
        int cpu;
        pr_info("exit module...\n");
        for_each_possible_cpu(cpu)
        {
            pr_info("cpuvar cpu%d = %ld\n", cpu, per_cpu(cpuvar, cpu));
            pr_info("exit: cpualloc%d = %ld\n", cpu, *per_cpu_ptr(cpualloc, cpu));
        }
        free_percpu(cpualloc);
        pr_info("Bye: module unloaded from 0x%p\n", my_exit);
    }
    module_init(my_init);
    module_exit(my_exit);
    MODULE_AUTHOR("WY");
    MODULE_LICENSE("GPL");
    
    [134657.935134] init: cpuvar on cpu0 = 5
    [134657.935134] init: cpuvar on cpu1 = 5
    [134657.935134] init: cpuvar on cpu2 = 10
    [134657.935135] init: cpuvar on cpu3 = 10
    [134657.935135] init: cpuvar on cpu4 = 10
    [134657.935135] init: cpuvar on cpu5 = 10
    [134657.935135] init: cpuvar on cpu6 = 10
    [134657.935135] init: cpuvar on cpu7 = 10
    [134657.935136] init: cpuvar on cpu8 = 10
    [134657.935136] init: cpuvar on cpu9 = 10
    [134657.935136] init: cpuvar on cpu10 = 10
    [134657.935137] init: cpuvar on cpu11 = 10
    [134657.935137] init: cpuvar on cpu12 = 10
    [134657.935137] init: cpuvar on cpu13 = 10
    [134657.935137] init: cpuvar on cpu14 = 10
    [134657.935137] init: cpuvar on cpu15 = 10
    [134657.935138] init: cpuvar on cpu16 = 10
    [134657.935138] init: cpuvar on cpu17 = 10
    [134657.935138] init: cpuvar on cpu18 = 10
    [134657.935138] init: cpuvar on cpu19 = 10
    [134657.935139] init: cpuvar on cpu20 = 10
    [134657.935139] init: cpuvar on cpu21 = 10
    [134657.935139] init: cpuvar on cpu22 = 10
    [134657.935139] init: cpuvar on cpu23 = 10
    [134657.935140] init: cpuvar on cpu24 = 10
    [134657.935140] init: cpuvar on cpu25 = 10
    [134657.935140] init: cpuvar on cpu26 = 10
    [134657.935140] init: cpuvar on cpu27 = 10
    [134657.935141] init: cpuvar on cpu28 = 10
    [134657.935141] init: cpuvar on cpu29 = 10
    [134657.935141] init: cpuvar on cpu30 = 10
    [134657.935141] init: cpuvar on cpu31 = 10
    [134657.935142] init: cpuvar on cpu32 = 10
    [134657.935142] init: cpuvar on cpu33 = 10
    [134657.935142] init: cpuvar on cpu34 = 10
    [134657.935142] init: cpuvar on cpu35 = 10
    [134657.935142] init: cpuvar on cpu36 = 10
    [134657.935143] init: cpuvar on cpu37 = 10
    [134657.935143] init: cpuvar on cpu38 = 10
    [134657.935143] init: cpuvar on cpu39 = 10
    [134657.935143] init: cpuvar on cpu40 = 10
    [134657.935144] init: cpuvar on cpu41 = 10
    [134657.935144] init: cpuvar on cpu42 = 10
    [134657.935144] init: cpuvar on cpu43 = 10
    [134657.935144] init: cpuvar on cpu44 = 10
    [134657.935145] init: cpuvar on cpu45 = 10
    [134657.935145] init: cpuvar on cpu46 = 10
    [134657.935145] init: cpuvar on cpu47 = 10
    [134657.935145] init: cpuvar on cpu48 = 10
    [134657.935146] init: cpuvar on cpu49 = 10
    [134657.935146] init: cpuvar on cpu50 = 10
    [134657.935146] init: cpuvar on cpu51 = 10
    [134657.935146] init: cpuvar on cpu52 = 10
    [134657.935147] init: cpuvar on cpu53 = 10
    [134657.935147] init: cpuvar on cpu54 = 10
    [134657.935147] init: cpuvar on cpu55 = 10
    [134657.935147] init: cpuvar on cpu56 = 10
    [134657.935148] init: cpuvar on cpu57 = 10
    [134657.935148] init: cpuvar on cpu58 = 10
    [134657.935148] init: cpuvar on cpu59 = 10
    [134657.935148] init: cpuvar on cpu60 = 10
    [134657.935149] init: cpuvar on cpu61 = 10
    [134657.935149] init: cpuvar on cpu62 = 10
    [134657.935149] init: cpuvar on cpu63 = 10
    [134657.935149] init: cpuvar on cpu64 = 10
    [134657.935150] init: cpuvar on cpu65 = 10
    [134657.935150] init: cpuvar on cpu66 = 10
    [134657.935150] init: cpuvar on cpu67 = 10
    [134657.935150] init: cpuvar on cpu68 = 10
    [134657.935151] init: cpuvar on cpu69 = 10
    [134657.935151] init: cpuvar on cpu70 = 10
    [134657.935151] init: cpuvar on cpu71 = 10
    [134657.935151] init: cpuvar on cpu72 = 10
    [134657.935151] init: cpuvar on cpu73 = 10
    [134657.935152] init: cpuvar on cpu74 = 10
    [134657.935152] init: cpuvar on cpu75 = 10
    [134657.935152] init: cpuvar on cpu76 = 10
    [134657.935152] init: cpuvar on cpu77 = 10
    [134657.935153] init: cpuvar on cpu78 = 10
    [134657.935153] init: cpuvar on cpu79 = 10
    [134657.935153] init: cpuvar on cpu80 = 10
    [134657.935153] init: cpuvar on cpu81 = 10
    [134657.935154] init: cpuvar on cpu82 = 10
    [134657.935154] init: cpuvar on cpu83 = 10
    [134657.935154] init: cpuvar on cpu84 = 10
    [134657.935154] init: cpuvar on cpu85 = 10
    [134657.935155] init: cpuvar on cpu86 = 10
    [134657.935155] init: cpuvar on cpu87 = 10
    [134657.935155] init: cpuvar on cpu88 = 10
    [134657.935155] init: cpuvar on cpu89 = 10
    [134657.935156] init: cpuvar on cpu90 = 10
    [134657.935156] init: cpuvar on cpu91 = 10
    [134657.935156] init: cpuvar on cpu92 = 10
    [134657.935156] init: cpuvar on cpu93 = 10
    [134657.935156] init: cpuvar on cpu94 = 10
    [134657.935157] init: cpuvar on cpu95 = 10
    [134657.935157] init: cpuvar on cpu96 = 10
    [134657.935157] init: cpuvar on cpu97 = 10
    [134657.935157] init: cpuvar on cpu98 = 10
    [134657.935158] init: cpuvar on cpu99 = 10
    [134657.935158] init: cpuvar on cpu100 = 10
    [134657.935158] init: cpuvar on cpu101 = 10
    [134657.935158] init: cpuvar on cpu102 = 10
    [134657.935159] init: cpuvar on cpu103 = 10
    [134657.935159] init: cpuvar on cpu104 = 10
    [134657.935159] init: cpuvar on cpu105 = 10
    [134657.935159] init: cpuvar on cpu106 = 10
    [134657.935160] init: cpuvar on cpu107 = 10
    [134657.935160] init: cpuvar on cpu108 = 10
    [134657.935160] init: cpuvar on cpu109 = 10
    [134657.935160] init: cpuvar on cpu110 = 10
    [134657.935161] init: cpuvar on cpu111 = 10
    [134657.935161] init: cpuvar on cpu112 = 10
    [134657.935161] init: cpuvar on cpu113 = 10
    [134657.935161] init: cpuvar on cpu114 = 10
    [134657.935162] init: cpuvar on cpu115 = 10
    [134657.935162] init: cpuvar on cpu116 = 10
    [134657.935162] init: cpuvar on cpu117 = 10
    [134657.935162] init: cpuvar on cpu118 = 10
    [134657.935163] init: cpuvar on cpu119 = 10
    [134657.935163] init: cpuvar on cpu120 = 10
    [134657.935163] init: cpuvar on cpu121 = 10
    [134657.935163] init: cpuvar on cpu122 = 10
    [134657.935164] init: cpuvar on cpu123 = 10
    [134657.935164] init: cpuvar on cpu124 = 10
    [134657.935164] init: cpuvar on cpu125 = 10
    [134657.935164] init: cpuvar on cpu126 = 10
    [134657.935165] init: cpuvar on cpu127 = 10
    [134657.935171] init: cpu:0 cpualloc = 666
    [134657.935171] init: cpu:1 cpualloc = 666
    [134657.935172] init: cpu:2 cpualloc = 666
    [134657.935172] init: cpu:3 cpualloc = 666
    [134657.935172] init: cpu:4 cpualloc = 666
    [134657.935172] init: cpu:5 cpualloc = 666
    [134657.935172] init: cpu:6 cpualloc = 666
    [134657.935173] init: cpu:7 cpualloc = 666
    [134657.935173] init: cpu:8 cpualloc = 666
    [134657.935173] init: cpu:9 cpualloc = 666
    [134657.935173] init: cpu:10 cpualloc = 666
    [134657.935173] init: cpu:11 cpualloc = 666
    [134657.935174] init: cpu:12 cpualloc = 666
    [134657.935174] init: cpu:13 cpualloc = 666
    [134657.935174] init: cpu:14 cpualloc = 666
    [134657.935174] init: cpu:15 cpualloc = 666
    [134657.935175] init: cpu:16 cpualloc = 666
    [134657.935175] init: cpu:17 cpualloc = 666
    [134657.935175] init: cpu:18 cpualloc = 666
    [134657.935175] init: cpu:19 cpualloc = 666
    [134657.935175] init: cpu:20 cpualloc = 666
    [134657.935176] init: cpu:21 cpualloc = 666
    [134657.935176] init: cpu:22 cpualloc = 666
    [134657.935176] init: cpu:23 cpualloc = 666
    [134657.935176] init: cpu:24 cpualloc = 666
    [134657.935177] init: cpu:25 cpualloc = 666
    [134657.935177] init: cpu:26 cpualloc = 666
    [134657.935177] init: cpu:27 cpualloc = 666
    [134657.935177] init: cpu:28 cpualloc = 666
    [134657.935178] init: cpu:29 cpualloc = 666
    [134657.935178] init: cpu:30 cpualloc = 666
    [134657.935178] init: cpu:31 cpualloc = 666
    [134657.935178] init: cpu:32 cpualloc = 666
    [134657.935179] init: cpu:33 cpualloc = 666
    [134657.935179] init: cpu:34 cpualloc = 666
    [134657.935179] init: cpu:35 cpualloc = 666
    [134657.935179] init: cpu:36 cpualloc = 666
    [134657.935179] init: cpu:37 cpualloc = 666
    [134657.935180] init: cpu:38 cpualloc = 666
    [134657.935180] init: cpu:39 cpualloc = 666
    [134657.935180] init: cpu:40 cpualloc = 666
    [134657.935180] init: cpu:41 cpualloc = 666
    [134657.935181] init: cpu:42 cpualloc = 666
    [134657.935181] init: cpu:43 cpualloc = 666
    [134657.935181] init: cpu:44 cpualloc = 666
    [134657.935181] init: cpu:45 cpualloc = 666
    [134657.935181] init: cpu:46 cpualloc = 666
    [134657.935182] init: cpu:47 cpualloc = 666
    [134657.935182] init: cpu:48 cpualloc = 666
    [134657.935182] init: cpu:49 cpualloc = 666
    [134657.935182] init: cpu:50 cpualloc = 666
    [134657.935183] init: cpu:51 cpualloc = 666
    [134657.935183] init: cpu:52 cpualloc = 666
    [134657.935183] init: cpu:53 cpualloc = 666
    [134657.935183] init: cpu:54 cpualloc = 666
    [134657.935183] init: cpu:55 cpualloc = 666
    [134657.935184] init: cpu:56 cpualloc = 666
    [134657.935184] init: cpu:57 cpualloc = 666
    [134657.935184] init: cpu:58 cpualloc = 666
    [134657.935184] init: cpu:59 cpualloc = 666
    [134657.935184] init: cpu:60 cpualloc = 666
    [134657.935185] init: cpu:61 cpualloc = 666
    [134657.935185] init: cpu:62 cpualloc = 666
    [134657.935185] init: cpu:63 cpualloc = 666
    [134657.935185] init: cpu:64 cpualloc = 666
    [134657.935194] init: cpu:65 cpualloc = 666
    [134657.935194] init: cpu:66 cpualloc = 666
    [134657.935194] init: cpu:67 cpualloc = 666
    [134657.935195] init: cpu:68 cpualloc = 666
    [134657.935195] init: cpu:69 cpualloc = 666
    [134657.935195] init: cpu:70 cpualloc = 666
    [134657.935195] init: cpu:71 cpualloc = 666
    [134657.935196] init: cpu:72 cpualloc = 666
    [134657.935196] init: cpu:73 cpualloc = 666
    [134657.935196] init: cpu:74 cpualloc = 666
    [134657.935196] init: cpu:75 cpualloc = 666
    [134657.935196] init: cpu:76 cpualloc = 666
    [134657.935197] init: cpu:77 cpualloc = 666
    [134657.935197] init: cpu:78 cpualloc = 666
    [134657.935197] init: cpu:79 cpualloc = 666
    [134657.935197] init: cpu:80 cpualloc = 666
    [134657.935198] init: cpu:81 cpualloc = 666
    [134657.935198] init: cpu:82 cpualloc = 666
    [134657.935198] init: cpu:83 cpualloc = 666
    [134657.935198] init: cpu:84 cpualloc = 666
    [134657.935198] init: cpu:85 cpualloc = 666
    [134657.935199] init: cpu:86 cpualloc = 666
    [134657.935199] init: cpu:87 cpualloc = 666
    [134657.935199] init: cpu:88 cpualloc = 666
    [134657.935200] init: cpu:89 cpualloc = 666
    [134657.935200] init: cpu:90 cpualloc = 666
    [134657.935200] init: cpu:91 cpualloc = 666
    [134657.935200] init: cpu:92 cpualloc = 666
    [134657.935201] init: cpu:93 cpualloc = 666
    [134657.935201] init: cpu:94 cpualloc = 666
    [134657.935201] init: cpu:95 cpualloc = 666
    [134657.935201] init: cpu:96 cpualloc = 666
    [134657.935202] init: cpu:97 cpualloc = 666
    [134657.935202] init: cpu:98 cpualloc = 666
    [134657.935202] init: cpu:99 cpualloc = 666
    [134657.935202] init: cpu:100 cpualloc = 666
    [134657.935203] init: cpu:101 cpualloc = 666
    [134657.935203] init: cpu:102 cpualloc = 666
    [134657.935203] init: cpu:103 cpualloc = 666
    [134657.935203] init: cpu:104 cpualloc = 666
    [134657.935203] init: cpu:105 cpualloc = 666
    [134657.935204] init: cpu:106 cpualloc = 666
    [134657.935204] init: cpu:107 cpualloc = 666
    [134657.935204] init: cpu:108 cpualloc = 666
    [134657.935204] init: cpu:109 cpualloc = 666
    [134657.935205] init: cpu:110 cpualloc = 666
    [134657.935205] init: cpu:111 cpualloc = 666
    [134657.935205] init: cpu:112 cpualloc = 666
    [134657.935205] init: cpu:113 cpualloc = 666
    [134657.935206] init: cpu:114 cpualloc = 666
    [134657.935206] init: cpu:115 cpualloc = 666
    [134657.935206] init: cpu:116 cpualloc = 666
    [134657.935206] init: cpu:117 cpualloc = 666
    [134657.935206] init: cpu:118 cpualloc = 666
    [134657.935207] init: cpu:119 cpualloc = 666
    [134657.935207] init: cpu:120 cpualloc = 666
    [134657.935207] init: cpu:121 cpualloc = 666
    [134657.935207] init: cpu:122 cpualloc = 666
    [134657.935208] init: cpu:123 cpualloc = 666
    [134657.935208] init: cpu:124 cpualloc = 666
    [134657.935208] init: cpu:125 cpualloc = 666
    [134657.935208] init: cpu:126 cpualloc = 666
    [134657.935209] init: cpu:127 cpualloc = 666
    

     

     参考

    内核必须懂(五): per-CPU变量 - 简书 (jianshu.com)

     

     

    更多相关内容
  • CPU卡读写操作源代码

    热门讨论 2015-04-22 16:02:04
    复旦F1208CPU卡的读写操作函数,1、CPUCPU卡激活;2、初始化CPU卡;3、创建文件和删除文件;4、修改文件密码;5、读写文件。全国首创,只需十分钟就可轻松搞定CPU卡!
  • CPU 执行程序的秘密,藏在了这 15 张图里

    万次阅读 多人点赞 2020-10-10 23:29:52
    CPU 看了那么多,我们都知道 CPU 通常分为 32 位和 64 位,你知道 64 位相比 32 位 CPU 的优势在哪吗?64 位 CPU 的计算性能一定比 32 位 CPU 高很多吗? 不知道也不用慌张,接下来就循序渐进..


    前言

    代码写了那么多,你知道 a = 1 + 2 这条代码是怎么被 CPU 执行的吗?

    软件用了那么多,你知道软件的 32 位和 64 位之间的区别吗?再来 32 位的操作系统可以运行在 64 位的电脑上吗?64 位的操作系统可以运行在 32 位的电脑上吗?如果不行,原因是什么?

    CPU 看了那么多,我们都知道 CPU 通常分为 32 位和 64 位,你知道 64 位相比 32 位 CPU 的优势在哪吗?64 位 CPU 的计算性能一定比 32 位 CPU 高很多吗?

    不知道也不用慌张,接下来就循序渐进的、一层一层的攻破这些问题。


    正文

    图灵机的工作方式

    要想知道程序执行的原理,我们可以先从「图灵机」说起,图灵的基本思想是用机器来模拟人们用纸笔进行数学运算的过程,而且还定义了计算机由哪些部分组成,程序又是如何执行的。

    图灵机长什么样子呢?你从下图可以看到图灵机的实际样子:

    图来源自:http://www.kristergustafsson.me/turing-machine/

    图灵机的基本组成如下:

    • 有一条「纸带」,纸带由一个个连续的格子组成,每个格子可以写入字符,纸带就好比内存,而纸带上的格子的字符就好比内存中的数据或程序;
    • 有一个「读写头」,读写头可以读取纸带上任意格子的字符,也可以把字符写入到纸带的格子;
    • 读写头上有一些部件,比如存储单元、控制单元以及运算单元:
      1、存储单元用于存放数据;
      2、控制单元用于识别字符是数据还是指令,以及控制程序的流程等;
      3、运算单元用于执行运算指令;

    知道了图灵机的组成后,我们以简单数学运算的 1 + 2 作为例子,来看看它是怎么执行这行代码的。

    • 首先,用读写头把 「1、2、+」这 3 个字符分别写入到纸带上的 3 个格子,然后读写头先停在 1 字符对应的格子上;

    • 接着,读写头读入 1 到存储设备中,这个存储设备称为图灵机的状态;

    • 然后读写头向右移动一个格,用同样的方式把 2 读入到图灵机的状态,于是现在图灵机的状态中存储着两个连续的数字, 1 和 2;

    • 读写头再往右移动一个格,就会碰到 + 号,读写头读到 + 号后,将 + 号传输给「控制单元」,控制单元发现是一个 + 号而不是数字,所以没有存入到状态中,因为 + 号是运算符指令,作用是加和目前的状态,于是通知「运算单元」工作。运算单元收到要加和状态中的值的通知后,就会把状态中的 1 和 2 读入并计算,再将计算的结果 3 存放到状态中;

    • 最后,运算单元将结果返回给控制单元,控制单元将结果传输给读写头,读写头向右移动,把结果 3 写入到纸带的格子中;

    通过上面的图灵机计算 1 + 2 的过程,可以发现图灵机主要功能就是读取纸带格子中的内容,然后交给控制单元识别字符是数字还是运算符指令,如果是数字则存入到图灵机状态中,如果是运算符,则通知运算符单元读取状态中的数值进行计算,计算结果最终返回给读写头,读写头把结果写入到纸带的格子中。

    事实上,图灵机这个看起来很简单的工作方式,和我们今天的计算机是基本一样的。接下来,我们一同再看看当今计算机的组成以及工作方式。


    冯诺依曼模型

    在 1945 年冯诺依曼和其他计算机科学家们提出了计算机具体实现的报告,其遵循了图灵机的设计,而且还提出用电子元件构造计算机,并约定了用二进制进行计算和存储,还定义计算机基本结构为 5 个部分,分别是中央处理器(CPU)、内存、输入设备、输出设备、总线

    这 5 个部分也被称为冯诺依曼模型,接下来看看这 5 个部分的具体作用。

    内存

    我们的程序和数据都是存储在内存,存储的区域是线性的。

    数据存储的单位是一个二进制位(bit,即 0 或 1。最小的存储单位是字节(byte,1 字节等于 8 位。

    内存的地址是从 0 开始编号的,然后自增排列,最后一个地址为内存总字节数 - 1,这种结构好似我们程序里的数组,所以内存的读写任何一个数据的速度都是一样的。

    中央处理器

    中央处理器也就是我们常说的 CPU,32 位和 64 位 CPU 最主要区别在于一次能计算多少字节数据:

    • 32 位 CPU 一次可以计算 4 个字节;
    • 64 位 CPU 一次可以计算 8 个字节;

    这里的 32 位和 64 位,通常称为 CPU 的位宽。

    之所以 CPU 要这样设计,是为了能计算更大的数值,如果是 8 位的 CPU,那么一次只能计算 1 个字节 0~255 范围内的数值,这样就无法一次完成计算 10000 * 500 ,于是为了能一次计算大数的运算,CPU 需要支持多个 byte 一起计算,所以 CPU 位宽越大,可以计算的数值就越大,比如说 32 位 CPU 能计算的最大整数是 4294967295

    CPU 内部还有一些组件,常见的有寄存器、控制单元和逻辑运算单元等。其中,控制单元负责控制 CPU 工作,逻辑运算单元负责计算,而寄存器可以分为多种类,每种寄存器的功能又不尽相同。

    CPU 中的寄存器主要作用是存储计算时的数据,你可能好奇为什么有了内存还需要寄存器?原因很简单,因为内存离 CPU 太远了,而寄存器就在 CPU 里,还紧挨着控制单元和逻辑运算单元,自然计算时速度会很快。

    常见的寄存器种类:

    • 通用寄存器,用来存放需要进行运算的数据,比如需要进行加和运算的两个数据。
    • 程序计数器,用来存储 CPU 要执行下一条指令「所在的内存地址」,注意不是存储了下一条要执行的指令,此时指令还在内存中,程序计数器只是存储了下一条指令的地址。
    • 指令寄存器,用来存放程序计数器指向的指令,也就是指令本身,指令被执行完成之前,指令都存储在这里。

    总线

    总线是用于 CPU 和内存以及其他设备之间的通信,总线可分为 3 种:

    • 地址总线,用于指定 CPU 将要操作的内存地址;
    • 数据总线,用于读写内存的数据;
    • 控制总线,用于发送和接收信号,比如中断、设备复位等信号,CPU 收到信号后自然进行响应,这时也需要控制总线;

    当 CPU 要读写内存数据的时候,一般需要通过两个总线:

    • 首先要通过「地址总线」来指定内存的地址;
    • 再通过「数据总线」来传输数据;

    输入、输出设备

    输入设备向计算机输入数据,计算机经过计算后,把数据输出给输出设备。期间,如果输入设备是键盘,按下按键时是需要和 CPU 进行交互的,这时就需要用到控制总线了。


    线路位宽与 CPU 位宽

    数据是如何通过地址总线传输的呢?其实是通过操作电压,低电压表示 0,高压电压则表示 1。

    如果构造了高低高这样的信号,其实就是 101 二进制数据,十进制则表示 5,如果只有一条线路,就意味着每次只能传递 1 bit 的数据,即 0 或 1,那么传输 101 这个数据,就需要 3 次才能传输完成,这样的效率非常低。

    这样一位一位传输的方式,称为串行,下一个 bit 必须等待上一个 bit 传输完成才能进行传输。当然,想一次多传一些数据,增加线路即可,这时数据就可以并行传输。

    为了避免低效率的串行传输的方式,线路的位宽最好一次就能访问到所有的内存地址。 CPU 要想操作的内存地址就需要地址总线,如果地址总线只有 1 条,那每次只能表示 「0 或 1」这两种情况,所以 CPU 一次只能操作 2 个内存地址;如果想要 CPU 操作 4G 的内存,那么就需要 32 条地址总线,因为 2 ^ 32 = 4G

    知道了线路位宽的意义后,我们再来看看 CPU 位宽。

    CPU 的位宽最好不要小于线路位宽,比如 32 位 CPU 控制 40 位宽的地址总线和数据总线的话,工作起来就会非常复杂且麻烦,所以 32 位的 CPU 最好和 32 位宽的线路搭配,因为 32 位 CPU 一次最多只能操作 32 位宽的地址总线和数据总线。

    如果用 32 位 CPU 去加和两个 64 位大小的数字,就需要把这 2 个 64 位的数字分成 2 个低位 32 位数字和 2 个高位 32 位数字来计算,先加个两个低位的 32 位数字,算出进位,然后加和两个高位的 32 位数字,最后再加上进位,就能算出结果了,可以发现 32 位 CPU 并不能一次性计算出加和两个 64 位数字的结果。

    对于 64 位 CPU 就可以一次性算出加和两个 64 位数字的结果,因为 64 位 CPU 可以一次读入 64 位的数字,并且 64 位 CPU 内部的逻辑运算单元也支持 64 位数字的计算。

    但是并不代表 64 位 CPU 性能比 32 位 CPU 高很多,很少应用需要算超过 32 位的数字,所以如果计算的数额不超过 32 位数字的情况下,32 位和 64 位 CPU 之间没什么区别的,只有当计算超过 32 位数字的情况下,64 位的优势才能体现出来

    另外,32 位 CPU 最大只能操作 4GB 内存,就算你装了 8 GB 内存条,也没用。而 64 位 CPU 寻址范围则很大,理论最大的寻址空间为 2^64


    程序执行的基本过程

    在前面,我们知道了程序在图灵机的执行过程,接下来我们来看看程序在冯诺依曼模型上是怎么执行的。

    程序实际上是一条一条指令,所以程序的运行过程就是把每一条指令一步一步的执行起来,负责执行指令的就是 CPU 了。

    那 CPU 执行程序的过程如下:

    • 第一步,CPU 读取「程序计数器」的值,这个值是指令的内存地址,然后 CPU 的「控制单元」操作「地址总线」指定需要访问的内存地址,接着通知内存设备准备数据,数据准备好后通过「数据总线」将指令数据传给 CPU,CPU 收到内存传来的数据后,将这个指令数据存入到「指令寄存器」。
    • 第二步,CPU 分析「指令寄存器」中的指令,确定指令的类型和参数,如果是计算类型的指令,就把指令交给「逻辑运算单元」运算;如果是存储类型的指令,则交由「控制单元」执行;
    • 第三步,CPU 执行完指令后,「程序计数器」的值自增,表示指向下一条指令。这个自增的大小,由 CPU 的位宽决定,比如 32 位的 CPU,指令是 4 个字节,需要 4 个内存地址存放,因此「程序计数器」的值会自增 4;

    简单总结一下就是,一个程序执行的时候,CPU 会根据程序计数器里的内存地址,从内存里面把需要执行的指令读取到指令寄存器里面执行,然后根据指令长度自增,开始顺序读取下一条指令。

    CPU 从程序计数器读取指令、到执行、再到下一条指令,这个过程会不断循环,直到程序执行结束,这个不断循环的过程被称为 CPU 的指令周期


    a = 1 + 2 执行具体过程

    知道了基本的程序执行过程后,接下来用 a = 1 + 2 的作为例子,进一步分析该程序在冯诺伊曼模型的执行过程。

    CPU 是不认识 a = 1 + 2 这个字符串,这些字符串只是方便我们程序员认识,要想这段程序能跑起来,还需要把整个程序翻译成汇编语言的程序,这个过程称为编译成汇编代码。

    针对汇编代码,我们还需要用汇编器翻译成机器码,这些机器码由 0 和 1 组成的机器语言,这一条条机器码,就是一条条的计算机指令,这个才是 CPU 能够真正认识的东西。

    下面来看看 a = 1 + 2 在 32 位 CPU 的执行过程。

    程序编译过程中,编译器通过分析代码,发现 1 和 2 是数据,于是程序运行时,内存会有个专门的区域来存放这些数据,这个区域就是「数据段」。如下图,数据 1 和 2 的区域位置:

    • 数据 1 被存放到 0x100 位置;
    • 数据 2 被存放到 0x104 位置;

    注意,数据和指令是分开区域存放的,存放指令区域的地方称为「正文段」。

    编译器会把 a = 1 + 2 翻译成 4 条指令,存放到正文段中。如图,这 4 条指令被存放到了 0x200 ~ 0x20c 的区域中:

    • 0x200 的内容是 load 指令将 0x100 地址中的数据 1 装入到寄存器 R0
    • 0x204 的内容是 load 指令将 0x104 地址中的数据 2 装入到寄存器 R1
    • 0x208 的内容是 add 指令将寄存器 R0R1 的数据相加,并把结果存放到寄存器 R2
    • 0x20c 的内容是 store 指令将寄存器 R2 中的数据存回数据段中的 0x108 地址中,这个地址也就是变量 a 内存中的地址;

    编译完成后,具体执行程序的时候,程序计数器会被设置为 0x200 地址,然后依次执行这 4 条指令。

    上面的例子中,由于是在 32 位 CPU 执行的,因此一条指令是占 32 位大小,所以你会发现每条指令间隔 4 个字节。

    而数据的大小是根据你在程序中指定的变量类型,比如 int 类型的数据则占 4 个字节,char 类型的数据则占 1 个字节。

    指令

    上面的例子中,图中指令的内容我写的是简易的汇编代码,目的是为了方便理解指令的具体内容,事实上指令的内容是一串二进制数字的机器码,每条指令都有对应的机器码,CPU 通过解析机器码来知道指令的内容。

    不同的 CPU 有不同的指令集,也就是对应着不同的汇编语言和不同的机器码,接下来选用最简单的 MIPS 指集,来看看机器码是如何生成的,这样也能明白二进制的机器码的具体含义。

    MIPS 的指令是一个 32 位的整数,高 6 位代表着操作码,表示这条指令是一条什么样的指令,剩下的 26 位不同指令类型所表示的内容也就不相同,主要有三种类型R、I 和 J。

    一起具体看看这三种类型的含义:

    • R 指令,用在算术和逻辑操作,里面由读取和写入数据的寄存器地址。如果是逻辑位移操作,后面还有位移操作的「位移量」,而最后的「功能码」则是再前面的操作码不够的时候,扩展操作码来表示对应的具体指令的;
    • I 指令,用在数据传输、条件分支等。这个类型的指令,就没有了位移量和操作码,也没有了第三个寄存器,而是把这三部分直接合并成了一个地址值或一个常数;
    • J 指令,用在跳转,高 6 位之外的 26 位都是一个跳转后的地址;

    接下来,我们把前面例子的这条指令:「add 指令将寄存器 R0R1 的数据相加,并把结果放入到 R3」,翻译成机器码。

    加和运算 add 指令是属于 R 指令类型:

    • add 对应的 MIPS 指令里操作码是 000000,以及最末尾的功能码是 100000,这些数值都是固定的,查一下 MIPS 指令集的手册就能知道的;
    • rs 代表第一个寄存器 R0 的编号,即 00000
    • rt 代表第二个寄存器 R1 的编号,即 00001
    • rd 代表目标的临时寄存器 R2 的编号,即 00010
    • 因为不是位移操作,所以位移量是 00000

    把上面这些数字拼在一起就是一条 32 位的 MIPS 加法指令了,那么用 16 进制表示的机器码则是 0x00011020

    编译器在编译程序的时候,会构造指令,这个过程叫做指令的编码。CPU 执行程序的时候,就会解析指令,这个过程叫作指令的解码。

    现代大多数 CPU 都使用来流水线的方式来执行指令,所谓的流水线就是把一个任务拆分成多个小任务,于是一条指令通常分为 4 个阶段,称为 4 级流水线,如下图:

    四个阶段的具体含义:

    1. CPU 通过程序计数器读取对应内存地址的指令,这个部分称为 Fetch(取得指令)
    2. CPU 对指令进行解码,这个部分称为 Decode(指令译码)
    3. CPU 执行指令,这个部分称为 Execution(执行指令)
    4. CPU 将计算结果存回寄存器或者将寄存器的值存入内存,这个部分称为 Store(数据回写)

    上面这 4 个阶段,我们称为指令周期(Instrution Cycle,CPU 的工作就是一个周期接着一个周期,周而复始。

    事实上,不同的阶段其实是由计算机中的不同组件完成的:

    • 取指令的阶段,我们的指令是存放在存储器里的,实际上,通过程序计数器和指令寄存器取出指令的过程,是由控制器操作的;
    • 指令的译码过程,也是由控制器进行的;
    • 指令执行的过程,无论是进行算术操作、逻辑操作,还是进行数据传输、条件分支操作,都是由算术逻辑单元操作的,也就是由运算器处理的。但是如果是一个简单的无条件地址跳转,则是直接在控制器里面完成的,不需要用到运算器。

    指令的类型

    指令从功能角度划分,可以分为 5 大类:

    • 数据传输类型的指令,比如 store/load 是寄存器与内存间数据传输的指令,mov 是将一个内存地址的数据移动到另一个内存地址的指令;
    • 运算类型的指令,比如加减乘除、位运算、比较大小等等,它们最多只能处理两个寄存器中的数据;
    • 跳转类型的指令,通过修改程序计数器的值来达到跳转执行指令的过程,比如编程中常见的 if-elseswtich-case、函数调用等。
    • 信号类型的指令,比如发生中断的指令 trap
    • 闲置类型的指令,比如指令 nop,执行后 CPU 会空转一个周期;

    指令的执行速度

    CPU 的硬件参数都会有 GHz 这个参数,比如一个 1 GHz 的 CPU,指的是时钟频率是 1 G,代表着 1 秒会产生 1G 次数的脉冲信号,每一次脉冲信号高低电平的转换就是一个周期,称为时钟周期。

    对于 CPU 来说,在一个时钟周期内,CPU 仅能完成一个最基本的动作,时钟频率越高,时钟周期就越短,工作速度也就越快。

    一个时钟周期一定能执行完一条指令吗?答案是不一定的,大多数指令不能在一个时钟周期完成,通常需要若干个时钟周期。不同的指令需要的时钟周期是不同的,加法和乘法都对应着一条 CPU 指令,但是乘法需要的时钟周期就要比加法多。

    如何让程序跑的更快?

    程序执行的时候,耗费的 CPU 时间少就说明程序是快的,对于程序的 CPU 执行时间,我们可以拆解成 CPU 时钟周期数(CPU Cycles)和时钟周期时间(Clock Cycle Time)的乘积

    时钟周期时间就是我们前面提及的 CPU 主频,主频越高说明 CPU 的工作速度就越快,比如我手头上的电脑的 CPU 是 2.4 GHz 四核 Intel Core i5,这里的 2.4 GHz 就是电脑的主频,时钟周期时间就是 1/2.4G。

    要想 CPU 跑的更快,自然缩短时钟周期时间,也就是提升 CPU 主频,但是今非彼日,摩尔定律早已失效,当今的 CPU 主频已经很难再做到翻倍的效果了。

    另外,换一个更好的 CPU,这个也是我们软件工程师控制不了的事情,我们应该把目光放到另外一个乘法因子 —— CPU 时钟周期数,如果能减少程序所需的 CPU 时钟周期数量,一样也是能提升程序的性能的。

    对于 CPU 时钟周期数我们可以进一步拆解成:「指令数 x 每条指令的平均时钟周期数(Cycles Per Instruction,简称 CPI」,于是程序的 CPU 执行时间的公式可变成如下:

    因此,要想程序跑的更快,优化这三者即可:

    • 指令数,表示执行程序所需要多少条指令,以及哪些指令。这个层面是基本靠编译器来优化,毕竟同样的代码,在不同的编译器,编译出来的计算机指令会有各种不同的表示方式。
    • 每条指令的平均时钟周期数 CPI,表示一条指令需要多少个时钟周期数,现代大多数 CPU 通过流水线技术(Pipline),让一条指令需要的 CPU 时钟周期数尽可能的少;
    • 时钟周期时间,表示计算机主频,取决于计算机硬件。有的 CPU 支持超频技术,打开了超频意味着把 CPU 内部的时钟给调快了,于是 CPU 工作速度就变快了,但是也是有代价的,CPU 跑的越快,散热的压力就会越大,CPU 会很容易奔溃。

    很多厂商为了跑分而跑分,基本都是在这三个方面入手的哦,特别是超频这一块。


    总结

    最后我们再来回答开头的问题。

    64 位相比 32 位 CPU 的优势在哪吗?64 位 CPU 的计算性能一定比 32 位 CPU 高很多吗?

    64 位相比 32 位 CPU 的优势主要体现在两个方面:

    • 64 位 CPU 可以一次计算超过 32 位的数字,而 32 位 CPU 如果要计算超过 32 位的数字,要分多步骤进行计算,效率就没那么高,但是大部分应用程序很少会计算那么大的数字,所以只有运算大数字的时候,64 位 CPU 的优势才能体现出来,否则和 32 位 CPU 的计算性能相差不大
    • 64 位 CPU 可以寻址更大的内存空间,32 位 CPU 最大的寻址地址是 4G,即使你加了 8G 大小的内存,也还是只能寻址到 4G,而 64 位 CPU 最大寻址地址是 2^64,远超于 32 位 CPU 最大寻址地址的 2^32

    你知道软件的 32 位和 64 位之间的区别吗?再来 32 位的操作系统可以运行在 64 位的电脑上吗?64 位的操作系统可以运行在 32 位的电脑上吗?如果不行,原因是什么?

    64 位和 32 位软件,实际上代表指令是 64 位还是 32 位的:

    • 如果 32 位指令在 64 位机器上执行,需要一套兼容机制,就可以做到兼容运行了。但是如果 64 位指令在 32 位机器上执行,就比较困难了,因为 32 位的寄存器存不下 64 位的指令
    • 操作系统其实也是一种程序,我们也会看到操作系统会分成 32 位操作系统、64 位操作系统,其代表意义就是操作系统中程序的指令是多少位,比如 64 位操作系统,指令也就是 64 位,因此不能装在 32 位机器上。

    总之,硬件的 64 位和 32 位指的是 CPU 的位宽,软件的 64 位和 32 位指的是指令的位宽。


    絮叨

    大家好,我是小林,一个专为大家图解的工具人,欢迎微信搜索「小林coding」,关注公众号,这里有好多图解等着你呢!

    另外,如果觉得文章对你有帮助,欢迎分享给你的朋友,也给小林点个「点和收藏」,这对小林非常重要,谢谢你们,我们下次见!


    推荐阅读

    读者问:小林怎么学操作系统和计算机网络呀?

    展开全文
  • 操作系统中cpu如何工作

    千次阅读 多人点赞 2022-01-19 14:28:47
    扩充小知识:   这些硬件设备在一条总线上链接,他们通过这条线进行数据交互,里面的带头大哥就是CPU,...我们通过上面知道了MMU是CPU的一部分,但是CPU有还要其他的部件吗?当然是有的啦,比如指令寄存器芯片,指令

    扩充小知识:

                              

    这些硬件设备在一条总线上链接,他们通过这条线进行数据交互,里面的带头大哥就是CPU,拥有最高指挥权。那么它是如何工作的呢?

      A.取指单元(从内存中取得指令);

      B.解码单元(完成解码[讲内存中取到的数据转换成CPU真正能运行的指令]);

      C.执行单元(开始执行指令,根据指令的需求去调用不同的硬件去干活。);

    我们通过上面知道了MMU是CPU的一部分,但是CPU有还要其他的部件吗?当然是有的啦,比如指令寄存器芯片,指令计数器芯片,堆栈指针。

      指令寄存器芯片:就是CPU用于将内存中的数据取出来存放的地方;

      指令计数器芯片:就是CPU为了记录上一次在内存中取数据的位置,方便下一次取值;

      堆栈指针:CPU每次取完指令后,就会把堆栈指针指向下一个指令在内存中的位置。

      他们的工作周期和CPU是一样快的速度,跟CPU的工作频率是在同一个时钟周期下,因此他的性能是非常好的,在CPU内部总线上完成数据通信。指令寄存器芯片,指令计数器芯片,堆栈指针。这些设备通常都被叫做CPU的寄存器。

      寄存器其实就是用于保存现场的。尤其是在时间多路复用尤为明显。比如说CPU要被多个程序共享使用的时候,CPU经常会终止或挂起一个进程,操作系统必须要把它当时的运行状态给保存起来(方便CPU一会回来处理它的时候可以继续接着上次的状态干活。)然后继续运行其他进程(这叫计算机的上下文切换)。

    三.计算机的存储体系。

    1.对称多处理器SMP

      CPU里面除了有MMU和寄存器(接近cpu的工作周期)等等,还有cpu核心,正是专门处理数据的,一颗CPU有多个核心,可以用于并行跑你的代码。工业上很多公司采用多颗CPU,这种结构我们称之为对称多处理器。

    2.程序局部性原理

      空间局部性:

        程序是由指令和数据组成的。空间局部性指的是一个数据被访问到之后,那么离这个数据很近的其他数据随后也可能会被访问到。

      时间局部性:

        一般而言当一个程序执行完毕后,可能很快会被访问到。数据也是同样的原理,一个数据的被访问到,很可能会再次访问到。

      正是因为程序局部性的存在,所以使得无论是在空间局部性或者时间的局部性的角度来考虑,一般而言我们都需要对数据做缓存。

    扩充小知识:

      由于CPU内部的寄存器存储的空间有限,于是就用了内存来存储数据,但是由于CPU和速度和内存的速度完全不在一个档次上,因此在处理的数据的时候回到多数都在等(CPU要在内存中取一个数据,cpu转一圈的时间就可以处理完,内存可能是需要转20圈)。为了解决使得效率更加提高,就出现了缓存这个概念。

      既然我们知道了程序的局部性原理,有知道了CPU为了获得更多的空间其实就是用时间去换空间,但是缓存就是可以直接让cpu拿到数据,节省了时间,所以说缓存就是用空间去换时间

    3.就算进存储体系

                                    

      工作时间就的朋友可能见过磁带机,现在基本上都被OUT了,企业很多都用机硬盘来替代磁带机了,所以我们这里就从我们最熟悉的家用电脑的结构来说,存下到上一次存储数据是不一样。我们可以简单举个例子,他们的周存储周期是有很大差距的。尤为明显的是机械硬盘和内存,他们两个存取熟读差距是相当大的。

    扩充小知识:

      相比自己家用的台式机或是笔记本可能自己拆开过,讲过机械式硬盘,固态硬盘或是内存等等。但是可能你没有见过缓存物理设备,其实他是在CPU上的。因此我们对它的了解可能会有些盲区。

    先说说一级缓存和耳机缓存吧,他们的CPU在这里面取数据的时候时间周期基本上查不了多少,因一级缓存和二级缓存都在CPU核心内部资源。(在其他硬件条件相同的情况下。一级缓存128k可能市场价格会买到300元左右,、一级缓存256k可能会买到600元左右,一级缓存512k可能市场价格就得过四位数这个具体价格可以参考京东啊。这足以说明缓存的造价是非常高的!)这个时候你可能会问那三级缓存呢?其实三级缓存就是就是多颗CPU共享的空间。当然多颗cpu也是共享内存的。

                               

    4.非一致性内存访问(NUMA)

      我们知道当多颗cpu共享三级缓存或是内存的时候,他们就会出现了一个问题,即资源征用。我们知道变量或是字符串在内存中被保存是有内存地址的。他们是如何去领用内存地址呢?我们可以参考下图:

                           

      没错,这些玩硬件的大牛们将三级缓存分割,分别让不同的CPU占用不同的内存地址,这样我们可以理解他们都有自己的三级缓存区域,不会存在资源抢夺的问题,但是要注意的是他们还是同一块三级缓存。就好像北京市有朝阳区,丰台区,大兴区,海淀区等等,但是他们都是北京的所属地。我们可以这里理解。这就是NUMA,他的特性就是:非一致性内存访问,都有自己的内存空间。

    扩展小知识:

      那么问题来了,基于重新负载的结果,如果cpu1运行的进程被挂起,其地址在他自己的它的缓存地址是有记录的,但是当cpu2再次运行这个程序的时候被CPU2拿到的它是如何处理的呢?

      这就没法了,只能从CPU1的三级换粗区域中复制一份地址过来一份或是移动过来一份让CPU2来处理,这个时候是需要一定时间的。所以说重新负载均衡会导致CPU性能降低。这个时候我们就可以用进程绑定来实现,让再次处理该进程的时候还是用之前处理的CPU来处理。即进程的CPU的亲缘性。

    5.缓存中的通写和回写机制。

                       

      CPU在处理数据的地方就是在寄存器中修改,当寄存器没有要找的数据是,就会去一级缓存找,如果一级缓存中没有数据就会去二级缓存中找,依次查找知道从磁盘中找到,然后在加载到寄存器中。当三级缓存从内存中取数据发现三级缓存不足时,就会自动清理三级缓存的空间。

      我们知道数据最终存放的位置是硬盘,这个存取过程是由操作系统来完成的。而我们CPU在处理数据是通过两种写入方式将数据写到不同的地方,那就是通写(写到内存中)和回写(写到一级缓存中)。很显然回写的性能好,但是如果断电的话就尴尬了,数据会丢失,因为他直接写到一级缓存中就完事了,但是一级缓存其他CPU是访问不到的,因此从可靠性的角度上来说通写方式会更靠谱。具体采用哪种方式得你自己按需而定啦。

    四.IO设备

    1.IO设备由设备控制器和设备本身组成。

      设备控制器:集成在主板的一块芯片活一组芯片。负责从操作系统接收命令,并完成命令的执行。比如负责从操作系统中读取数据。

      设备本身:其有自己的接口,但是设备本身的接口并不可用,它只是一个物理接口。如IDE接口。

    扩展小知识:

      每个控制器都有少量的用于通信的寄存器(几个到几十个不等)。这个寄存器是直接集成到设备控制器内部的。比方说,一个最小化的磁盘控制器,它也会用于指定磁盘地址,扇区计数,读写方向等相关操作请求的寄存器。所以任何时候想要激活控制器,设备驱动程序从操作系统中接收操作指令,然后将它转换成对应设备的基本操作,并把操作请求放置在寄存器中才能完成操作的。每个寄存器表现为一个IO端口。所有的寄存器组合称为设备的I/O地址空间,也叫I/O端口空间,

    2.驱动程序

      真正的硬件操作是由驱动程序操作完成的。驱动程序通常应该由设备生产上完成,通常驱动程序位于内核中,虽然驱动程序可以在内核外运行,但是很少有人这么玩,因为它太低效率啦!

    3.实现输入和输出

      设备的I/O端口没法事前分配,因为各个主板的型号不一致,所以我们需要做到动态指定。电脑在开机的时候,每个IO设备都要想总线的I/o端口空间注册使用I/O端口。这个动态端口是由所有的寄存器组合成为设备的I/O地址空间,有2^16次方个端口,即65535个端口。

                  

      如上图所示,我们的CPU有要想跟指定设备打交道,就需要把指令传给驱动,然后驱动讲CPU的指令转换成设备能理解的信号放在寄存器中(也可以叫套接字,socket).所以说寄存器(I/O端口)是CPU通过总线和设备打交道的地址(I/O端口)。

    展开全文
  • CPU架构:CPU架构详细介绍

    万次阅读 多人点赞 2020-04-25 10:12:43
    CPU架构是CPU商给CPU产品定的一个规范,主要目的是为了区分不同类型的CPU。目前市场上的CPU分类主要分有两大阵营,一个是intel、AMD为首的复杂指令集CPU,另一个是以IBM、ARM为首的精简指令集CPU。不同品牌的CPU,...

    1 概述

             CPU架构是CPU商给CPU产品定的一个规范,主要目的是为了区分不同类型的CPU。目前市场上的CPU分类主要分有两大阵营,一个是intel、AMD为首的复杂指令集CPU,另一个是以IBM、ARM为首的精简指令集CPU。不同品牌的CPU,其产品的架构也不相同,Intel、AMD的CPU是X86架构,IBM公司的CPU是PowerPC架构,ARM公司的CPU是ARM架构,国内的飞腾CPU也是ARM架构。此外还有MPIS架构、SPARC架构、Alpha架构。

    2 X86架构

            X86架构(The X86 architecture)是微处理器执行的计算机语言指令集。X86指令集是美国Intel公司为其第一块16位CPU(i8086)专门开发的,美国IBM公司1981年推出的世界第一台PC机中的CPU--i8088(i8086简化版)使用的也是X86指令。同时电脑中为提高浮点数据处理能力而增加的X87芯片系列数字协处理器则另外使用X87指令,,包括后来 Intel 80186、80286、80386以及80486,由于以“86”作为结尾,以后就将X86指令集和X87指令集统称为X86指令集。虽然随着CPU技术的不断发展,Intel陆续研制出更新型的i80386、i80486直到今天的Pentium 4(以下简为P4)系列,但为了保证电脑能继续运行以往开发的各类应用程序以保护和继承丰富的软件资源,所以Intel公司所生产的所有CPU仍然继续使用X86指令集,所以它的CPU仍属于X86系列。

           x86架构CPU主要应用领域:个人计算机、服务器等。在PC端市场Wintel组合(windows系统 + intel处理器)占据了大部分江山,另外一部分有ADM占领。目前国内有兆芯,从AMD和VIA获取授权,研发自己的X86CPU,有其它国产CPU + 国产操作系统(linux系)可以用于教育和事业单位以及军工行针对的是特殊用户,国产CPU和操作系统想进入民用市场,由于性能、价格以及生态系统等,仍需要继续优化打磨以及一个合适契机。

         x86指令集发展

           IA:Intel(英特尔)处理器的服务器称之为IA(Intel Architecture)架构服务器

          IA-32:英特尔32位体系架构,X86从16位到32位是在原有的架构基础上进行修改(Intel称之为IA-32)

          x86-32:现如今Intel把x86-32称为IA-32

          x86-64 分为intel和AMD

           AMD64:x86架构的64位拓展,向后兼容于16位及32位的x86架构。x64于1999年由AMD设计,AMD首次公开64位集以扩展给x86,称为“AMD64”,AMD64和Intel64基本上一致

           Intel64:EM64T(Extended Memory 64 Technology)扩展64bit内存技术,本质上和AMD64一样都是IA-32的增强版本。

           IA-64:64位的英特尔架构,英特尔安腾架构(Intel Itanium architecture),使用在Itanium处理器家族上的64位指令集架构,由英特尔公司与惠普公司共同开发。IA是Intel Architecture(英特尔架构)的缩写,64指64位系统。使用这种架构的CPU,包括Itanium和Itanium 2。此架构与x86及x86-64并不相容,操作系统与软件需使用IA-64专用版本。

           Intel推出X86架构已满40年了,同486相比,Pentium向前迈进了一大步, 而PⅡ的前进步伐则没有这么大了,X86 CPU的发展似乎已到了尽头。英特尔非常清楚,是X86指令集限制了CPU性能的进一步提高,因此,他们正同惠普共同努力开发下一代指令集架构(Instruction Set Architecture ,ISA): EPIC(Explicitly Parallel Instruction Computing,显性并行指令计算)。对英特尔而言, IA-64(英特尔的64位架构)是下一个10到15年的架构。新的ISA将使英特尔摆脱X86架构的限制,从而设计出超越所有现有RISC CPU和X86 CPU的新型处理器。

    3 ARM架构

            ARM架构,也称作进阶精简指令集机器(Advanced RISC Machine,更早称作:Acorn RISC Machine),是一个32位精简指令集(RISC)处理器架构,其广泛地使用在许多嵌入式系统设计。由于节能的特点,ARM处理器非常适用于行动通讯领域,符合其主要设计目标为低耗电的特性。(其它请参考ARM介绍

            目前,ARM家族占了所有32位嵌入式处理器75%的比例,使它成为占全世界最多数的32位架构之一。ARM处理器可以在很多消费性电子产品上看到,从可携式装置(PDA、移动电话、多媒体播放器、掌上型电子游戏,和计算机)到电脑外设(硬盘、桌上型路由器)甚至在导弹的弹载计算机等军用设施中都有他的存在。在此还有一些基于ARM设计的派生产品,重要产品还包括Marvell的XScale架构和德州仪器的OMAP系列。

              ARM 授权方式:ARM 公司本身并不靠自有的设计来制造或出售 CPU ,而是将处理器架构授权给有兴趣的厂家。ARM 提供了多样的授权条款,包括售价与散播性等项目。对于授权方来说,ARM 提供了 ARM 内核的整合硬件叙述,包含完整的软件开发工具(编译器、debugger、SDK),以及针对内含 ARM CPU 硅芯片的销售权。对于无晶圆厂的授权方来说,其希望能将 ARM 内核整合到他们自行研发的芯片设计中,通常就仅针对取得一份生产就绪的智财核心技术(IP Core)认证。对这些客户来说,ARM 会释出所选的 ARM 核心的闸极电路图,连同抽象模拟模型和测试程式,以协助设计整合和验证。需求更多的客户,包括整合元件制造商(IDM)和晶圆厂家,就选择可合成的RTL(暂存器转移层级,如 Verilog)形式来取得处理器的智财权(IP)。借着可整合的 RTL,客户就有能力能进行架构上的最佳化与加强。这个方式能让设计者完成额外的设计目标(如高震荡频率、低能量耗损、指令集延伸等)而不会受限于无法更动的电路图。虽然 ARM 并不授予授权方再次出售 ARM 架构本身,但授权方可以任意地出售制品(如芯片元件、评估板、完整系统等)。商用晶圆厂是特殊例子,因为他们不仅授予能出售包含 ARM 内核的硅晶成品,对其它客户来讲,他们通常也保留重制 ARM 内核的权利。

            国外生产厂商:TI (德州仪器)、Samsung(三星)、Freescale(飞思卡尔)、Marvell(马维尔)、Nvidia(英伟达)、Qualcomm(高通)、STMicroelectronics(意法半导体)。

            国内生产厂商:华为(海思芯片)、飞腾(FT-1500、FT2000-4等CPU芯片)、兆易创新(GD32系列MCU,参考STM32系列)、瑞芯微(RK系列芯片)、联发科(台湾,天玑系列)。

          ARM架构的CPU可以有多核,例如几年前联发科推出10核处理器Helio X20(被戏称一核有难,八核围观,国产FT处理器已经推出了16核处理器。但是由于ARM自身低功耗等因素的限制,核心数多并不一定能大大提升性能。

           目前ARM主要市场是手机端CPU和MCU,手机CPU市场,由高通骁龙系列、华为麒麟系列、以及三星猎户系列和联发科系列,在MCU端主要是STM32以及国产的GD32,其它厂商的芯片用于其它领域,比如汽车电子、智能家居等。在CPU处理器上,有华为海思的鲲鹏920CPU(应用于泰山服务器中)和FT的CPU(军工领域),虽然FT的CPU起步很早,但是鲲鹏显然有后来居上之趋势。国内ARM芯片做的最好的是华为海思,鲲鹏920CPU性能在ARM架构中是NO1,另外海思麒麟系列手机芯片已发展为全球前三的地位,海思的视频处理芯片以及IoT芯片,在行业中都是标杆的产品。

          在2020年11月11日,apple公司发布了新一代的mac book,亮点就是使用了apple自己的ARM架构的M1。由于ARM的功耗小,在新一代的macbook上,apple大胆的去掉了散热风扇芯片,将笔记本厚度进一步压缩,续航时间达到了18小时。同时,搭载M1芯片的mac book CPU 性能提升至 3.5 倍,GPU 性能提升至 5 倍,机器学习性能提升至 9 倍。根据apple公司的影响力,未来PC中市场将会被ARM架构的CPU替代。(天下苦wintel久已)

    4 MPIS架构

           MIPS是世界上很流行的一种RISC处理器。MIPS的意思是“无内部互锁流水级的微处理器”(Microprocessor without interlockedpipedstages),其机制是尽量利用软件办法避免流水线中的数据相关问题。它最早是在80年代初期由斯坦福(Stanford)大学Hennessy教授领导的研究小组研制出来的。MIPS公司的R系列就是在此基础上开发的RISC工业产品的微处理器。这些系列产品为很多计算机公司采用构成各种工作站和计算机系统。

            MIPS技术公司是美国著名的芯片设计公司,它采用精简指令系统计算结构(RISC)来设计芯片。和英特尔采用的复杂指令系统计算结构(CISC)相比,RISC具有设计更简单、设计周期更短等优点,并可以应用更多先进的技术,开发更快的下一代处理器。MIPS是出现最早的商业RISC架构芯片之一,新的架构集成了所有原来MIPS指令集,并增加了许多更强大的功能。MIPS自己只进行CPU的设计,之后把设计方案授权给客户,使得客户能够制造出高性能的CPU。

           1984年,MIPS计算机公司成立,开始设计RISC处理器;

           1986年推出R2000处理器。

           1992年,SGI收购了MIPS计算机公司。

           1988年推R3000处理器。

          1991年推出第一款64位商用微处器R4000;之后又陆续推出R8000(于1994年)、R10000(于1996年)和R12000(于1997年)等型号。

          1998年,MIPS脱离SGI,成为MIPS技术公司;随后,MIPS公司的战略发生变化,把重点放在嵌入式系统;1998年-MIPS科技股票在美国纳斯达克股票交易所公开上市。

          1999年,MIPS公司发布MIPS32和MIPS64架构标准,为未来MIPS处理器的开发奠定了基础。新的架构集成了所有原来NIPS指令集,并且增加了许多更强大的功能。MIPS公司陆续开发了高性能、低功耗的32位处理器内核(core)MIPS324Kc与高性能64位处理器内核MIPS645Kc。

          2000年,MIPS公司发布了针对MIPS32 4Kc的版本以及64位MIPS 64 20Kc处理器内核。

          2007年8月16日-MIPS科技宣布,中科院计算机研究所的龙芯中央处理器获得其处理器IP的全部专利和总线、指令集授权。

          2007年12月20日-MIPS科技宣布,扬智科技已取得其针对先进多媒体所设计的可定制化系统单芯片(SoC)核心“MIPS32 24KEcPro”授权。

    龙芯

           MPIS架构授权和ARM架构授权不一样,ARM架构授权用户基本不能自行修改,而MPIS架构授权后,可以自己修改。目前MPIS发扬光大寄希望中科龙芯公司,龙芯处理器从龙芯1号,到现在的龙芯3号系列的3A4000,CPU的性能已经大幅度提高,在完全可以胜任日常办公或者作为特殊用途的服务器。龙芯CPU和国产的飞腾(FT)处理器并驾齐驱,发展我国自主可控CPU。

    5 PowerPC系列

             PowerPC 是一种精简指令集(RISC)架构的中央处理器(CPU),其基本的设计源自IBM(国际商用机器公司)的IBMPowerPC 601 微处理器POWER(PerformanceOptimized With Enhanced RISC;《IBM Connect 电子报》2007年8月号译为“增强RISC性能优化”)架构。二十世纪九十年代,IBM(国际商用机器公司)、Apple(苹果公司)和Motorola(摩托罗拉)公司开发PowerPC芯片成功,并制造出基于PowerPC的多处理器计算机。PowerPC架构的特点是可伸缩性好、方便灵活。

            PowerPC 处理器有广泛的实现范围,包括从诸如 Power4 那样的高端服务器CPU 到嵌入式 CPU 市场(任天堂Gamecube 使用了 PowerPC)。PowerPC处理器有非常强的嵌入式表现,因为它具有优异的性能、较低的能量损耗以及较低的散热量。除了象串行和以太网控制器那样的集成 I/O,该嵌入式处理器与“台式机”CPU 存在非常显著的区别。

     

    6 SPARC架构

           SPARC架构(Scalable Processor ARChitecture,可扩展处理器架构)是国际上流行的RISC处理器体系架构之一,SPRAC如今已发展成为一个开放的标准,任何机构或个人均可研究或开发基于SPRAC架构的产品,而无需交纳版权费。SPARC 处理器架构具备精简指令集(RISC)、支持32 位/64 位指令精度,架构运行稳定、可扩展性优良、体系标准开放等特点。SPARC因此得以迅速发展壮大,在现在已经有大约3万多个成功的应用案例。

             SPARCV7/V8 是目前嵌入式控制系统常用的处理器标准版本,并在航天设备的电子系统中得到广泛应用。然而,SPARC只是一个处理器的架构标准,并不提供现成的源码或IP核,具体的芯片实现要由开发者去完成。

             运行Oracle Solaris的Oracle SPARC T4服务器提供了创世界纪录的性能,其单线程性能提高了5倍、内存容量高达2 TB且实现了极高的系统吞吐量和I/O容量。SPARC T4服务器适用于需要极高的可靠性、可用性和集成式片上加密加速的企业应用程序和任务关键型应用程序,可确保最终的安全性。

    7 Alpha架构

            Alpha处理器最早由DEC公司设计制造,在Compaq(康柏)公司收购DEC之后,Alpha处理器继续得到发展,并且应用于许多高档的Compaq服务器上。自1995年开始开发了21164芯片,那时的工艺为0.5um,主频为200MHz。1998年,推出新型号21264,当时的主频是600MHz。较新的21264芯片主频达到1GHz,工艺为0.18um。在该芯片具有完善的指令预测能力和很高的存储系统带宽(超过1GB/s),并且其中增加了处理视频信息的功能,其多媒体处理能力得到了增强。

          Alpha架构于1992年2月25日,在东京召开的一次会议上面被正式推介,新架构的关键特性都一一的被罗列出来。当时说Alpha只是产品开发的内部代号。新处理器采用完全64-bit RISC设计,执行固定长度指令(32 bits)。有32个64 bit整数寄存器,操作43-bit的虚拟地址(在后来能够扩充到64-bit)。和VAX相同,使用little-endian字节顺序,即低字节的寄存器占用低内存地址线。而不像如摩托罗拉等大多数处理器所使用的big-endian字节顺序,即低字节寄存器占用高内存地址线。除此之外,处理器还内建一个算术协处理器,有32个浮点64-bit寄存器,采用随机存取,而不是在intel x86协处理器上使用的堆栈存取方式。整个Alpha的生命周期被设计为至少25年。

            Alpha处理器被用于DEC自己的工作站和服务器中。作为VAX的后续被开发,支持VMS操作系统,如 Digital UNIX。不久之后开放源代码的操作系统也可以在其上运行,如Linux和 DSB 。Microsoft 支持这款处理器,直到Windows NT 4.0 SP6 ,但是从Windows 2000 RC2开始放弃了对Alpha的支持。

        目前国内采用此架构的是申微超算处理器,得益于国家的支持,申威处理器在军队应用广泛。

    8 架构之间的竞争

    8.1 PC和服务竞争

             PC端和服务器端是X86架构的天下,而X86架构基本是以Intel为首,AMD为辅二分天下之势。国产CPU基本只能用在军工行业或者事业单位等。其实说性能,powerpc,可谓是高出不胜寒。硬件方面,Power系统在可靠性、可用性和可维护性的方面的出色表现使得 IBM从芯片到系统所设计的整机方案有着独有的优势。Power架构的处理器在超算、大型企业的UNIX服务器等多个方面应用也十分成功。在软件方面,其专用的AIX系统在稳定性、软件方案集成度和厂商技术支持能力方面都要更强。由于用户选一平台主要看软件需求,一般对数据保护和7*24小时不宕机等有所要求,power架构的稳定性和运维等方面相对更优。但是,由于IBM的技术把控,使得其价格太不友好,同时技术也赶不上环境的变化,在云计算兴起后,随着分布式系统逐渐成熟,系统对小型机的依赖开始降低,改为依靠集群提供,性能也可实现分布式处理。而更为关键的是,IBM的全套服务尽管稳定性优秀,但却影响了Power架构对其他商家的吸引力。

            而Sparc架构和Power架构基本犯了同样的错误:价格不友好。SPARC架构测成功和Sun旗下的Solaris系统有着密不可分的关系。当计算机系统庞大、用户数量巨大增加时,基于Unix操作系统打造的 Solaris能更好地利用计算机资源,是所有商业版中最可靠最完善的版本。而依赖SPARC架构和Solaris系统的性能和可靠性,其占领了服务器高端市场。Sun的另一个更为知名的产品是Java,虽然在上世纪90年代为智能家电开发的Java并没有为其带来相应的回报,但已成为今天移动时代最重要的开发语言。如此强大的实力本应统领服务器市场,但遗憾的是,在windows和英特尔组成Wintel联盟之后,两者凭借自身在各自市场的规模效应,使得采用Wintel产品的服务器厂商可以通过低廉的价格大肆抢占中低端市场。而当Sun醒悟过来,通过开源等方式想要挽回败局时为时已晚。

            X86架构与Power和SPARC在高性能领域的风生水起不同,x86架构是天生的小屌丝。1978年他出生的那年,英特尔还只是一个普通的科技公司。可是x86架构随同其cisc指令集却开启了一个新的时代。x86之所以可以赢得市场主要原因在于其是一个十分开放的架构。IBM和SUN当年都是从芯片到服务器到系统一手包办的公司。而英特尔则是一个十分纯粹的芯片厂商,其业务仅与AMD等少数芯片生产者存在竞争,这就使得服务器厂商不用忌惮与之发生竞争关系。

            单从性能来看,无论Power还是SPARC架构都可以击溃x86,可是最终能够赢下来的却偏偏是"最弱"的x86架构。这并非劣币淘汰良币,而是市场竞争的选择,根源上讲,x86的成功在于英特尔根本不碰服务器。因此不论设备生产商、软件开发者或者系统开发者都可以与不存在利益竞争关系的英特尔合作。受益于此,x86架构的兼容性也越发强大,生态体系越发完善,这才成就了现如今市场占有率超过90%的一家独大局面,英特尔也借助x86架构一跃成为全球顶级的芯片提供商。

    8.2 移动端竞争

            正如PC和服务器端是X86的天下一样,移动端是ARM的天下。Intel在CPU界的大名,可谓家喻户晓,但是在手机登移动端却难以看到英国ARM公司背影。在2006年,自从AMD的64位处理器发布以来,AMD成功逆袭了Intel,市场占有率大幅上升,而Intel老迈的P4处理器则是腹背受敌,尽失昔日霸气,市场表现一路走低。为了稳住投资人的信心,最好的做法自然是让公司持续盈利,为此Intel进行大规模的重整,包括上任新CEO 欧德宁、大规模裁员、以及出售XScale手机处理器业务。正因为这个举措,使得Intel到达了人生巅峰,从PC市场有赚的钵满盆满,然而也是因为此,Intel忽视了移动领域的迅猛发展。(当年,Intel拒绝了乔帮主还是PPT的Iphone手机,不然是否就会不一样?但是想一下Iphone X 使用Intel基带,信号差的诟病,Intel做手机芯是否会臭名昭著也未可知)

            和Intel公司不同, ARM公司不制造,不销售芯片,而是只自己设计IP核,包括指令集架构、微处理器、GPU、互连架构等,然后谁想用就授权卖给谁,再从每颗实际造出来的产品中收取版税。ARM有三种授权模式,分别是架构授权、内核授权、使用授权,分别对应大中小公司,非常讨喜,贴个牌子就能说是自己的CPU,为ARM处理器的广泛使用打下坚实基础。

            ARM的成功除了商业模式的独特之外还少不得自身素质的优秀,Intel技术毫无疑问是顶尖的,但应用场景在传统PC上,换成移动设备就行不通了,移动设备比起性能首先要考虑功耗和续航,Intel就吃了这个大亏,X86架构独步天下肯定是不能随意变改的,移动设备当然继续沿用X86架构,然而换来却是高功耗和快速掉电,换谁都看不上。反之功耗控制则是ARM的强项,使用精简指令集(RISC)和创新的big.LITTLE架构,使ARM处理器能耗比一直领先于Intel。

            Intel正在积极布局,推出应用于 IoT 物联网的 Atom E3900 及车载电子的 Atom A3900 系列,号称 CPU 性能提升70%,GPU 性能提升190%,其中 Atom A3900 特别针对高温环境设计,可在110°C高温下使用15年。Intel是一家伟大的企业,但也是会犯错误的,既然已经错失移动市场,不妨暂时脱离,提前做好下一阶段的技术研发(5G),也有可能实现弯道超车。

     

     

    展开全文
  • 【Linux CPUFreq模块】

    千次阅读 2022-04-03 00:35:50
    Linux cpufreq kernel-4.19持续更新
  • CPU C-state & cpuidle driver

    千次阅读 2020-07-15 15:14:12
    为了在CPU空闲时节约能源,可以命令CPU进入低功耗模式。C-state是intel CPU处于空闲时的一种状态,CPU有几种电源模式,它们统称为“c状态”或“c模式” 低功耗模式最初是在486DX4处理器中引入的。到目前为止,已经...
  • 如何写出让 CPU 跑得更快的代码

    万次阅读 多人点赞 2020-10-18 17:12:57
    CPU 内部嵌入了 CPU Cache(高速缓存),它的存储容量很小,但是离 CPU 核心很近,所以缓存的读写速度是极快的,那么如果 CPU 运算时,直接从 CPU Cache 读取数据,而不是从内存的话,运算速度就会很快。 但是,...
  • 很多用户都知道电脑里有cpu,电脑的大脑就是cpu,但是不知道什么叫cpucpu具体是什么意思,英文的全称是central processingunit也就是中央处理器。下面来看看详细的cpu介绍吧。什么叫cpuCPU是英文:Central ...
  • 怎么样调电脑cpu电压啊

    千次阅读 2021-07-29 07:57:10
    开机进入BIOS设置项dvanced--Frequency/Voltage ControlCPU Voltage:CPU电压调节功能,设定范围1.1-1.85v。通过它,用户可以自行调节CPU的工作电压bios电压相关调节选项CPU Ratio:CPU倍频调节功能。 CPU HOST ...
  • 计算机组成原理——CPU

    万次阅读 多人点赞 2021-11-25 19:59:21
    计算机组成原理——CPU一:CPU模型二:指令周期1、时钟周期2、机器周期(CPU周期)3、指令周期 一:CPU模型 二:指令周期 1、时钟周期 时钟周期:时钟周期是CPU的基本时间计量单位,它是CPU一切操作的计时标准和基本...
  • 十分钟教你掌握CPU缓存

    千次阅读 多人点赞 2021-04-07 10:30:33
    基础知识 首先,大家都知道现在CPU的多核技术,都会有几级缓存,现在的CPU会有三级内存(L1,L2, L3),如下图所示。
  • 线程/进程和核绑定(CPU亲和性)

    千次阅读 2021-03-01 15:04:13
    文章目录前言一、CPU亲和性1 前言2 为何要手动绑定线程/进程到CPU核3 多进程和多线程在多核CPU上运行:4 应用场景举例二、Linux的CPU亲和性特征1 软亲和性2 硬亲和性3 硬亲和性使用场景三、查看CPU的核1 使用指令2 ...
  • 17 Redis 的性能受CPU结构影响

    万次阅读 2021-12-07 20:30:37
    17 Redis 的性能受CPU结构影响前言一、主流的 CPU 架构二、CPU 多核对 Redis 性能的影响三、CPU 的 NUMA 架构对 Redis 性能的影响四、绑核的风险和解决方案方案一:一个 Redis 实例对应绑一个物理核方案二:优化 ...
  • linux 系统内可以通过sysfs 文件系统查看/sys/devices/system/cpu目录内当前所使用的cpu详细信息,不仅可以查到单核cpu,还可以查看多核cpu以及NUMA系统内的cpu信息,还可以查看每个cpu包含的cache详细信息,以便对...
  • linux查看cpu状态相关命令

    千次阅读 2022-04-01 14:41:49
    linux查看cpu状态相关命令
  • 1.CPU-ZCPU-Z是一款家喻户晓的CPU检测软件,是检测CPU使用程度最高的一款软件,除了使用Intel或AMD自己的检测软件之外,我们平时使用最多的此类软件就数它了。它支持的CPU种类相当全面,软件的启动速度及检测速度都...
  • cpufreq schedutil原理剖析

    千次阅读 2021-02-10 17:00:00
    本文会基于Android Pixel4(android linux kernel 4.14+ARMv8(AArch64)),重点分析schedutil这个cpufreq的governor,...
  • Linux CPU负载性能监测

    千次阅读 2021-11-02 20:48:52
    Linux CPU性能监测平均负载和 CPU 使用率压测命令 stress模拟负载场景监测工具topmpstatpidstat补充:自愿上下文切换和非自愿上下文切换 平均负载和 CPU 使用率 平均负载是指单位时间内的活跃进程数,也就是处于可...
  • CPU中断

    万次阅读 2019-08-31 21:03:36
    CPU共256个中断类型型号: 0~31:对应于异常和非屏蔽中断,不使用中断控制器; 32~47:分配给可屏蔽中断,由I/O设备引起的中断,这其中就包含可由两个8259A级联响应的15个; 48~255:用来标识软中断; CPU...
  • 1、引言本系列文章介绍如何修复 Elasticsearch 集群的常见错误和问题。这是系列文章的第二篇,主要探讨:Elasitcsearch CPU 使用率突然飙升,怎么办?2、Elast...
  • 1、查看cpu的方法 cat /proc/cpuinfo 2、查看内存使用 free -m total:表示物理,内存总量 used:总计分配给缓存(包含Buffer和cache)使用的数量,但其中可能部分缓存并未实际使用 free:未被分配的内存。是...
  • WindowsVC++获取CPU整体使用率

    千次下载 热门讨论 2013-03-20 10:19:54
    《Windows系统CPU内存网络性能统计第二篇 CPU CPU整体使用率》 http://blog.csdn.net/morewindows/article/details/8678359 配套程序。 讲解了在Windows系统下使用VC++获取系统CPU整体使用率。已经测试,能运行于...
  • cpu可以说是电脑的心脏,作为电脑的核心存在,cpu性能对电脑性能的影响不言而喻。虽然说因为人民币贬值,cpu价格全面上涨近10%,但是游戏还是得照玩呀,面对配置要求越来越高的新游戏,电脑性能跟不上怎么办?买!小编...
  • 在深度学习模型训练过程中,在服务器端或者本地pc端,输入nvidia-smi来观察显卡的GPU内存占用率(Memory-Usage),显卡的GPU利用率(GPU-util),然后采用top来查看CPU的线程数(PID数)和利用率(%CPU)。...
  • 【计算机组成原理】CPU是什么

    千次阅读 多人点赞 2020-08-20 17:18:05
    CPU是什么CPU是什么?CPU 实际做什么?CPU的内部结构CPU 是寄存器的集合体计算机语言汇编语言程序计数器条件分支和循环机制标志寄存器通过地址和索引实现数组CPU 指令执行过程 CPU是什么? CPU 的全称是 Central ...
  • Q1:CPU高主频好还是多核数好? 游戏需求  如果是主打游戏,由于游戏需要的是最简单粗暴的计算工作,这方面多核心有点无用武之地。因此,目前主流游戏都是双核心调用,四核或者更多核心的比较少。  也就是说,...
  • 本文介绍了Android Studio CPU profiler性能分析工具的使用,以及如何使用Android Studio CPU profiler解决我们的APP耗时,卡顿等问题。
  • leomoon-cpu-v(查看cpu是否支持x64)
  • 我所理解的CPU中断

    千次阅读 2022-03-18 16:28:51
    CPU来说就是:CPU在执行某一段程序的时候收到某些特定信号转而去执行另一段特定程序的过程。 那为什么需要中断呢?原因是CPU不能闷着头啥也不管一个劲的只管执行代码,还得和连接在主板上的其它硬件打交道。经常...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,368,815
精华内容 947,526
关键字:

cpu

友情链接: 词法分析实验.zip