CPU调优

一、中断的CPU亲和性

我们可以调整中断到某个CPU上,这样可以让CPU更有效的利用起来。

 

1.关闭 irqbalance 服务

/etc/init.d/irqbalance stop 

Stopping irqbalance: [  OK  ]

 

2.查看中断所使用的CPU

for f in `find . -name "smp_affinity"`; doecho -ne "$f->" && cat $f; done

./18/smp_affinity->1

./17/smp_affinity->3

./15/smp_affinity->1

./14/smp_affinity->1

./13/smp_affinity->3

./12/smp_affinity->1

./11/smp_affinity->3

./10/smp_affinity->3

./9/smp_affinity->3

./8/smp_affinity->3

./7/smp_affinity->3

./6/smp_affinity->3

./5/smp_affinity->3

./4/smp_affinity->3

./3/smp_affinity->3

./2/smp_affinity->3

./1/smp_affinity->3

./0/smp_affinity->3

 

3.查看中断使用率

cat /proc/interrupts

           CPU0      CPU1       

  0:        137         0   IO-APIC-edge      timer

  1:          7         1   IO-APIC-edge      i8042

  3:          0         1   IO-APIC-edge    

  4:          1         0   IO-APIC-edge    

  7:          0         0   IO-APIC-edge      parport0

  8:          0         0   IO-APIC-edge      rtc0

  9:          0         0   IO-APIC-fasteoi   acpi

 12:        103         2   IO-APIC-edge      i8042

 14:       2301       628   IO-APIC-edge      ata_piix

 15:        116        49   IO-APIC-edge      ata_piix

 17:         15         0   IO-APIC-fasteoi   ioc0

 18:       4122        39   IO-APIC-fasteoi   eth0

NMI:          0         0   Non-maskable interrupts

LOC:      18423     16772   Local timer interrupts

SPU:          0         0   Spurious interrupts

PMI:          0         0   Performance monitoring interrupts

PND:          0         0   Performance pending work

RES:       2740      2914   Rescheduling interrupts

CAL:        110      1349   Function call interrupts

TLB:        339       421   TLB shootdowns

TRM:          0         0   Thermal event interrupts

THR:          0         0   Threshold APIC interrupts

MCE:          0         0   Machine check exceptions

MCP:          3         3   Machine check polls

ERR:          0

MIS:          0

 

我们看一下18号中断下的相关文件

cd /proc/irq/18/ && ls

affinity_hint  eth0  node  smp_affinity spurious

 

我们看下它使用的CPU

more smp_affinity 

1

 

注:这里输出为1表示,它使用了第一个CPU,1对映的两进制掩码也是1.

如果它使用前两个CPU,那么这里就是3,即二进制的11.

如果我们有4个处理器,这里的值就应该是F,也就是二进制1111.

如果我们只要第2个处理器进行处理,这里的值就应该是2,因为2的二进制是10.

 

 

我们在另一台服务器ping本机

 

ping 192.168.75.135

64 bytes from 192.168.75.135: icmp_seq=3454 ttl=64time=2.80 ms

64 bytes from 192.168.75.135: icmp_seq=3455 ttl=64time=3.80 ms

64 bytes from 192.168.75.135: icmp_seq=3456 ttl=64time=0.814 ms

64 bytes from 192.168.75.135: icmp_seq=3457 ttl=64time=0.293 ms

64 bytes from 192.168.75.135: icmp_seq=3458 ttl=64time=1.84 ms

64 bytes from 192.168.75.135: icmp_seq=3459 ttl=64time=0.265 ms

64 bytes from 192.168.75.135: icmp_seq=3460 ttl=64time=0.021 ms

64 bytes from 192.168.75.135: icmp_seq=3461 ttl=64time=0.793 ms

64 bytes from 192.168.75.135: icmp_seq=3462 ttl=64time=0.285 ms

64 bytes from 192.168.75.135: icmp_seq=3463 ttl=64time=0.038 ms

64 bytes from 192.168.75.135: icmp_seq=3464 ttl=64time=0.936 ms

64 bytes from 192.168.75.135: icmp_seq=3465 ttl=64time=0.279 ms

64 bytes from 192.168.75.135: icmp_seq=3466 ttl=64time=0.706 ms

 

 

在本机监控网卡中断分布

 

while ((1)) ; do sleep 1; cat /proc/interrupts |grepeth0; done

 18:       5568        39   IO-APIC-fasteoi   eth0

 18:       5570        39   IO-APIC-fasteoi   eth0

 18:       5576        39   IO-APIC-fasteoi   eth0

 18:       5580        39   IO-APIC-fasteoi   eth0

 18:       5584        39   IO-APIC-fasteoi   eth0

 18:       5590        39   IO-APIC-fasteoi   eth0

 18:       5592        39   IO-APIC-fasteoi   eth0

 18:       5598        39   IO-APIC-fasteoi   eth0

 18:       5604        39   IO-APIC-fasteoi   eth0

 18:       5606        39   IO-APIC-fasteoi   eth0

 18:       5612        39   IO-APIC-fasteoi   eth0

 18:       5616        39   IO-APIC-fasteoi   eth0

 18:       5620        39   IO-APIC-fasteoi   eth0

 18:       5626        39   IO-APIC-fasteoi   eth0

 18:       5628        39   IO-APIC-fasteoi   eth0

 18:       5634        39   IO-APIC-fasteoi   eth0

 18:       5638        39   IO-APIC-fasteoi   eth0

 18:       5641        39   IO-APIC-fasteoi   eth0

 18:       5647        39   IO-APIC-fasteoi   eth0

 18:       5650        39   IO-APIC-fasteoi   eth0

 18:       5656        39   IO-APIC-fasteoi   eth0

 

我们看到当前的中断(第二列)即所有的网卡中断请求都分布到了CPU0.

 

 

我们这里指定前两个CPU做为处理网卡请求

 

echo "3" > smp_affinity

 

while ((1)) ; do sleep 1; cat /proc/interrupts |grepeth0; done

 18:       6430        50   IO-APIC-fasteoi   eth0

 18:       6433        53   IO-APIC-fasteoi   eth0

 18:       6439        53   IO-APIC-fasteoi   eth0

 18:       6441        53   IO-APIC-fasteoi   eth0

 18:       6443        57   IO-APIC-fasteoi   eth0

 18:       6444        58   IO-APIC-fasteoi   eth0

 18:       6447        61   IO-APIC-fasteoi   eth0

 18:       6449        61   IO-APIC-fasteoi   eth0

 18:       6453        63   IO-APIC-fasteoi   eth0

 18:       6459        63   IO-APIC-fasteoi   eth0

 18:       6459        65   IO-APIC-fasteoi   eth0

 18:       6462        68   IO-APIC-fasteoi   eth0

 18:       6463        69   IO-APIC-fasteoi   eth0

 18:       6467        71   IO-APIC-fasteoi   eth0

 18:       6469        71   IO-APIC-fasteoi   eth0

 18:       6472        73   IO-APIC-fasteoi   eth0

 

注:我们看到网卡的中断请求已经平均的分配到了两个CPU.

 

 

二、isolcpus

通过在grub中设定isolcpus内核参数可以指定哪几个CPU在系统中是孤立的,也就是说默认它们将不被使用.

 

测试如下:

编辑/boot/grub/menu.list

 

在加载内核的选项后加入isolcpus=0,如下:

kernel /boot/vmlinuz-2.6.32-71.el6.i686 roroot=UUID=96262e00-91a3-432d-b225-cb35d29eec8f rhgb quiet isolcpus=0

 

也就是说我们在启动系统时将默认不使用CPU0,注意这里说的默认不使用并不是绝对的,操作系统仍然可以指定使用哪个CPU.对于用户而言可以通过taskset来做到这点.

 

重启系统后,我们查看进程的亲和性,如下:

 

ps -eo pid,args:50,psr 

  PID COMMAND                                          PSR

    1 /sbin/init                                         1

    2 [kthreadd]                                         0

    3 [migration/0]                                      0

    4 [ksoftirqd/0]                                      0

    5 [watchdog/0]                                       0

    6 [migration/1]                                      1

    7 [ksoftirqd/1]                                      1

    8 [watchdog/1]                                       1

    9 [events/0]                                         0

   10 [events/1]                                         1

   11 [cpuset]                                           0

   12 [khelper]                                          0

   13 [netns]                                            0

   14 [async/mgr]                                        0

   15 [pm]                                               0

   16 [sync_supers]                                      1

   17 [bdi-default]                                      0

   18 [kintegrityd/0]                                    0

   19 [kintegrityd/1]                                    1

   20 [kblockd/0]                                        0

   21 [kblockd/1]                                        1

   22 [kacpid]                                           0

   23 [kacpi_notify]                                     0

   24 [kacpi_hotplug]                                    0

   25 [ata/0]                                            0

   26 [ata/1]                                            1

   27 [ata_aux]                                          0

   28 [ksuspend_usbd]                                    0

   29 [khubd]                                            0

   30 [kseriod]                                          0

   33 [khungtaskd]                                       0

   34 [kswapd0]                                          0

   35 [ksmd]                                             0

   36 [aio/0]                                            0

   37 [aio/1]                                            1

   38 [crypto/0]                                         0

   39 [crypto/1]                                         1

   45 [kpsmoused]                                        0

   46 [usbhid_resumer]                                   0

   75 [kstriped]                                         0

  239 [scsi_eh_0]                                        0

  240 [scsi_eh_1]                                        0

  250 [mpt_poll_0]                                       0

  251 [mpt/0]                                            0

  252 [scsi_eh_2]                                        0

  301 [jbd2/sda1-8]                                      0

  302 [ext4-dio-unwrit]                                  0

  303 [ext4-dio-unwrit]                                  1

  324 [flush-8:0]                                        0

  390 /sbin/udevd -d                                     1

  643 /sbin/udevd -d                                     1

  644 /sbin/udevd -d                                     1

  731 [kauditd]                                          0

 1004 auditd                                             1

 1029 /sbin/rsyslogd -c 4                                1

 1062 irqbalance                                         1

 1081 rpcbind                                            1

 1093 mdadm --monitor --scan -f--pid-file=/var/run/mdad   1

 1102 dbus-daemon --system                               1

 1113 NetworkManager --pid-file=/var/run/NetworkManager/  1

 1117 /usr/sbin/modem-manager                            1

 1124 /sbin/dhclient -d -4 -sf/usr/libexec/nm-dhcp-clie   1

 1129 /usr/sbin/wpa_supplicant -c/etc/wpa_supplicant/wp   1

 1131 avahi-daemon: registering [linux.local]             1

 1132 avahi-daemon: chroot helper                         1

 1149 rpc.statd                                          1

 1186 [rpciod/0]                                         0

 1187 [rpciod/1]                                         1

 1194 rpc.idmapd                                         1

 1204 cupsd -C /etc/cups/cupsd.conf                       1

 1229 /usr/sbin/acpid                                    1

 1238 hald                                               1

 1239 hald-runner                                        1

 1279 hald-addon-input: Listening on/dev/input/event2 /   1

 1283 hald-addon-acpi: listening on acpid socket/var/ru   1

 1303 automount --pid-file /var/run/autofs.pid            1

 1326 /usr/sbin/sshd                                     1

 1456 /usr/libexec/postfix/master                         1

 1463 pickup -l -t fifo -u                               1

 1464 qmgr -l -t fifo -u                                 1

 1467 /usr/sbin/abrtd                                    1

 1475 crond                                              1

 1486 /usr/sbin/atd                                      1

 1497 libvirtd --daemon                                  1

 1553 /sbin/mingetty /dev/tty1                            1

 1558 /sbin/mingetty /dev/tty2                            1

 1561 /sbin/mingetty /dev/tty3                            1

 1564 /sbin/mingetty /dev/tty4                            1

 1567 /sbin/mingetty /dev/tty5                            1

 1569 /sbin/mingetty /dev/tty6                            1

 1586 /usr/sbin/dnsmasq --strict-order--bind-interfaces   1

 1598 sshd: root@pts/0                                   1

 1603 -bash                                              1

 

我们看到有一些内核线程比如[kblockd/0]占用了CPU0,这是因为它指定了在CPU0上执行.其余的进程占用了CPU1.

 

我们这里用一个简单的循环程序测试一下:

 

#include <stdio.h>

 

int

main ()

{

while(1){

}

return 0;

}

 

gcc test.c

 

./a.out&

./a.out&

./a.out&

./a.out&

 

查看a.out进程的程序亲和性,如下:

 

ps -eo pid,args:50,psr |grep a.out

 1669 ./a.out                                            1

 1670 ./a.out                                            1

 1671 ./a.out                                            1

 1672 ./a.out                                            1

 1675 grep a.out                                         1

 

我们看到4个a.out进程都使用了CPU1.这正是我们想看到的.

 

最后要说明的是如果使用isolcpus=1,则系统默认会使用CPU0提供服务.如果我们只有两个cpu,却指定isolcpus=0,1,这时将默认使用CPU0.

 

三、cpu热插拔

 

在操作系统层面可以对cpu进行热插拔.

 

动态关闭cpu1,如下:

echo "0" > /sys/devices/system/cpu/cpu1/online 

 

此时我们在系统中,只能看到1个CPU了.

cat /proc/cpuinfo 

processor       : 0

vendor_id       : AuthenticAMD

cpu family      : 15

model           : 107

model name      : AMD Sempron(tm) DualCore Processor 2300

stepping        : 2

cpu MHz         : 2210.053

cache size      : 256 KB

fdiv_bug        : no

hlt_bug         : no

f00f_bug        : no

coma_bug        : no

fpu             : yes

fpu_exception   : yes

cpuid level     : 1

wp              :yes

flags           : fpu vme depse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsrsse sse2 syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow constant_tsc uptsc_reliable extd_apicid pni cx16 lahf_lm extapic 3dnowprefetch

bogomips        : 4420.10

clflush size    : 64

cache_alignment : 64

address sizes   : 36 bits physical, 48 bitsvirtual

power management: ts fid vid ttp tm stc 100mhzsteps

 

注意,如果运行的程序跑在cpu1上,如果把cpu1关闭,则程序会迁移到cpu0上.另外cpu0是不可以被关闭的,在cpu0的sys文件系统中没有online文件.

 

四、进程/线程的亲和性和taskset的应用

 

1. 概述

1) CPU的亲和性分为软亲合性和硬亲合性,软亲合性是使进程并不会在处理器之间频繁迁移.硬亲合性是使进程需要在您指定的处理器上运行,Linux默认是软亲合性的,所以Linux会试图保持进程在相同的CPU上运行,因为这样再次应用TLB将成为可能.

 

2) Linux系统通过亲和性掩码使应用程序使用哪个CPU来运行程序,Linux默认的亲合性掩码是使用所有的CPU.

 

3) 应用程序可以在启动时指定亲和性掩码,提交给调度系统,也可以在应用程序运行中调整它的亲和性掩码.

 

 

2. taskset调整进程亲和性

我们先弄一个最简单的程序,它是一个死循环,如下:

 

#include <stdio.h>

 

int

main ()

{

        while(1){

        }

        return 0;

}

 

编译并运行:

gcc taskloop.c -o taskloop

./taskloop

 

我们在另一个终端查看该进程的状态,如下:

ps -eo pid,args:30,psr 

 PID COMMAND                         PSR

 2826 ./taskloop                      0

 

注:上面的ps输出,我们只保留了taskloop一行,PSR代表我们的程序用了哪个CPU,如果有两个CPU,就分别CPU0,CPU1,也就是从0开始.

 

我们中止这个程序,用taskset来指定它用CPU1来运行,如下:

 

taskset 2 ./taskloop

 

我们在另一个终端查看该进程的状态,如下:

ps -eo pid,args:30,psr 

 PID COMMAND                         PSR

 2892 ./taskloop                      1

 

注:通过taskset对亲合性掩码的设定,我们选择了CPU1来运行这个程序,这里要说明的是taskset指定的掩码是从1开始计算的,我们指定用CPU1,就得用taskset 2 COMMAND来设定.

 

下面是亲合性掩码与CPU的对映,如下:

0x00000001是处理器1(CPU0)

0x00000002是处理器2(CPU1)

0x00000003是处理器1和处理器2(CPU0/CPU1)

0x00000004是处理器3(CPU2)

0x0000001F是前5个处理器(CPU0,CPU1,CPU2,CPU3,CPU4)

0xFFFFFFFF是所有的处理器(即32个处理器)

 

以此类推,上面是十六进制的掩码方式,在taskset中可以用十六进制和十进制两种方式,我们为了方便,在这里只用十进制来表示.

 

同样的我们也可以在程序运行中来改变它的亲合性掩码,从而改变它使用的CPU.

 

上面的taskloop进程使用了CPU1,我们将它改为使用CPU0,如下:

taskset -p 1 `pgrep taskloop`  

pid 2892's current affinity mask: 2

pid 2892's new affinity mask: 1

 

在另一个终端查看该进程的状态:

ps -eo pid,args:30,psr

 PID COMMAND                         PSR

 2892 ./taskloop                      0

 

注:我们看到原本运行于CPU1的进程改用了CPU0,这里要说明的是如果我们程序在sleep或pause,此时改变它的亲合性掩码但它不会选用新的CPU,只有当sleep或pause结束,它才会应用亲和性掩码.

 

3.进程亲核性设置

通过sched_setaffinity函数,可以设置CPU的亲和性,让指定的进程运行于指定的CPU上,我们把之前的程序做一下变动,如下:

 

#define _GNU_SOURCE

#include <sched.h>

#include <stdio.h>

 

int main(){

    cpu_set_t mask;

    CPU_ZERO(&mask);

    CPU_SET(1,&mask);

    if(sched_setaffinity(0,sizeof(cpu_set_t), &mask)==-1)

       printf("sched_setaffinity set error!");

    while(1){

    }

    return 0;

}

编译并运行:

gcc proaffinity.c -o proaffinity

./proaffinity

 

在另一个终端查看该进程的状态:

ps -eo pid,args:20,psr|grep proaffinity|grep -v grep           

 3088 ./proaffinity         1

 

注:在程序中我们用sched_setaffinity函数,设定本程序用亲合性掩码1,也就是用第一个处理器来运行此程序.

sched_setaffinity(0, sizeof(cpu_set_t), &mask)函数中的第一个参数是PID,如果是0,则代表进程自己,第二个参数是亲合性掩码的长度,第三个参数是亲合性掩码.

CPU_ZERO(&mask)宏调用是清理掩码mask,CPU_SET(1,&mask)是设定掩码mask为1.

 

4.线程亲核性设置

通过pthread_attr_setaffinity_np函数,设定线程的亲合性掩码,也就是用第几个处理器来运行该线程,如下:

 

#define _GNU_SOURCE

#include <stdio.h>

#include <pthread.h>

#include <unistd.h>

 

int GetCpuCount()

{

    return(int)sysconf(_SC_NPROCESSORS_ONLN);

}

 

void *thread_fun()

{

    int i;

    while(1)

    {

        i = 0;

    }

 

    return NULL;

}

 

int main()

{

    int cpu_num = 0;

    cpu_num  = GetCpuCount();

    printf("The number of cpu is%d\n", cpu_num);

 

    pthread_t t1;

    pthread_t t2;

    pthread_attr_t attr1;

    pthread_attr_t attr2;

 

    pthread_attr_init(&attr1);

    pthread_attr_init(&attr2);

 

    cpu_set_t cpu_info;

    CPU_ZERO(&cpu_info);

    CPU_SET(0, &cpu_info);

    if(0!=pthread_attr_setaffinity_np(&attr1, sizeof(cpu_set_t), &cpu_info))

    {

        printf("set affinityfailed");

        return;

    }

 

    CPU_ZERO(&cpu_info);

    CPU_SET(1, &cpu_info);

    if(0!=pthread_attr_setaffinity_np(&attr2, sizeof(cpu_set_t), &cpu_info))

    {

        printf("set affinityfailed");

    }

 

    if (0!=pthread_create(&t1,&attr1, thread_fun, NULL))

    {

        printf("create thread1 error\n");

        return;

    }

 

    if (0!=pthread_create(&t2,&attr2, thread_fun, NULL))

    {

        printf("create thread2 error\n");

        return;

    }

 

    pthread_join(t1, NULL);

    pthread_join(t2, NULL);

}

 

编译并运行:

gcc pthraffinity.c -o pthraffinity -pthread

 

./proaffinity

 

我们在另一个终端查看该进程中所有线程的状态,如下:

 

ps -eLo pid,lwp,args:20,psr

  PID   LWP COMMAND             PSR

 3191  3191 ./pthraffinity        1

 3191  3192 ./pthraffinity        0

 3191  3193 ./pthraffinity        1

 

注:LWP一列为线程ID,我们看到进程(PID=3191)用了CPU0,而第一个线程(LWP=3192)用了CPU0,这正是程序中设定的,而第二个线程(LWP=3193)用了CPU1,这也是程序的意图.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Speccpu2017调优指的是对Speccpu2017测试套件进行性能优化的过程。Speccpu2017是一个基准测试套件,用于评估计算机的处理器性能。在调优过程中,我们需要针对不同的基准测试进行优化,以达到最佳性能。 首先,我们可以通过调整编译器优化选项来提高性能。在编译程序时,我们可以选择启用不同的优化选项,例如优化级别、循环展开、向量化等,以获得更高的性能。通过仔细分析测试程序的特点和需求,选择适当的优化选项,可以显著提升整体性能。 其次,我们可以通过硬件优化来提高性能。这包括调整处理器的频率和电压,以达到更高的性能水平。同时,还可以调整内存子系统、缓存配置和总线宽度等硬件参数,以最大程度地发挥处理器的性能潜力。 此外,我们还可以进行代码级别的优化。例如,消除循环里的无用计算、减少内存访问、合并函数调用等,都可以有效提高程序的性能。优化算法和数据结构的选择也是重要的一步,它们可以大大降低程序运行的时间复杂度,从而提升整体性能。 最后,调优过程中还需进行性能分析与调试。通过性能分析工具,我们可以定位程序中的性能瓶颈,并针对性地进行优化。在调试过程中,应注意避免过度优化,以免引入新的bug或不稳定性。 综上所述,Speccpu2017调优是一个复杂且综合性的过程,需要综合考虑软硬件优化以及代码调优等方面的内容。通过合理和有效的调优策略,可以提高计算机的处理器性能,从而实现更好的性能表现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值