首頁 > 軟體

Linux CPU數、物理核、邏輯核的檢視方法及執行緒進程的系結方法

2020-06-16 16:49:59

CPU數,物理核,邏輯核的關係:

邏輯CPU個數 > 物理CPU個數 * CPU核心數 開啟了超執行緒
邏輯CPU個數 = 物理CPU個數 * CPU核心數 沒有開啟超執行緒

CPU數,物理核,邏輯核的檢視方法:

#cat /proc/cpuinfo

processor  : 0
vendor_id  :GenuineIntel
cpu family  :6
model    :26
model name :Intel(R) Xeon(R) CPU          E5520  @ 2.27GHz
stepping    :5
cpu MHz    :1600.000
cache size  : 8192 KB
physical id  :0
siblings    :8
core id     : 0
cpu cores   :4
apicid        :0
fpu       :yes
fpu_exception :yes
cpuid level   : 11
wp      :yes
flags      : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc pni monitor ds_cpl vmx est tm2 cx16 xtpr popcnt lahf_lm
bogomips   :4522.12
clflush size  :64
cache_alignment  : 64
address sizes    : 40 bits physical, 48 bits virtual
power management :
以上輸出項的含義如下:
processor :系統中邏輯處理核的編號。對於單核處理器,則課認為是其CPU編號,對於多核處理器則可以是物理核、或者使用超執行緒技術虛擬的邏輯核
vendor_id :CPU製造商     
cpu family :CPU產品系列代號
model   :CPU屬於其系列中的哪一代的代號
model name:CPU屬於的名字及其編號、標稱主頻
stepping   :CPU屬於製作更新版本
cpu MHz   :CPU的實際使用主頻
cache size  :CPU二級快取大小
physical id  :單個CPU的標號
siblings      :單個CPU邏輯物理核數
core id        :當前物理核在其所處CPU中的編號,這個編號不一定連續
cpu cores    :該邏輯核所處CPU的物理核數
apicid          :用來區分不同邏輯核的編號,系統中每個邏輯核的此編號必然不同,此編號不一定連續
fpu            :是否具有浮點運算單元(Floating Point Unit)
fpu_exception  :是否支援浮點計算異常
cpuid level  :執行cpuid指令前,eax暫存器中的值,根據不同的值cpuid指令會返回不同的內容
wp            :表明當前CPU是否在核心態支援對使用者空間的防寫(Write Protection)
flags          :當前CPU支援的功能
bogomips  :在系統核心啟動時粗略測算的CPU速度(Million Instructions Per Second)
clflush size  :每次重新整理快取的大小單位
cache_alignment :快取地址對齊單位
address sizes    :可存取地址空間位數
power management :對能源管理的支援,有以下幾個可選支援功能:
  ts:  temperature sensor
  fid:   frequency id control
  vid:  voltage id control
  ttp:  thermal trip
  tm:
  stc:
  100mhzsteps:
  hwpstate:

processor:邏輯核的個數(邏輯核的id)
physical id:物理CPU的id
cpu cores:每個物理CPU的物理核個數
siblings:每個物理CPU上邏輯CPU個數
core id:每個CPU上的物理核的id

檢視CPU(各個邏輯核)佔用情況:

# top
remark:在top命令下,點選"1"可以檢視各個邏輯核的占用情況

進程系結邏輯核:

#include <stdio.h> 
//g++ -o test test.cpp
/*
啟動兩個範例,將進程都系結到Cpu0:
taskset -c 0 ./test
taskset -c 0 ./test
通過top, 輸入“1”檢視系統cpu狀況:
Cpu1空閒,Cpu0使用100%
繼續測試,將pid為18057的test遷移到CPU1上執行,執行:
$ taskset -pc  1 18057
pid 18057's current affinity list: 0
pid 18057's new affinity list: 1
Cpu0及Cpu1都進入忙碌狀態了!
繼續測試!將pid為18210的test也遷移到Cpu1上執行,執行:
Cpu0閒著,Cpu1忙碌起來了!
*/

void main(int argc, char** argv) 

        for(int i = 0; i<=10000000000000; i++) 
        { 
                if(i == 100000000) 
                { 
                        i = 0; 
                        printf("program is running!n"); 
                } 
        } 

執行緒系結邏輯核:

CPU親合力就是指在Linux系統中能夠將一個或多個進程系結到一個或多個處理器上執行.
一個進程的CPU親合力掩碼決定了該進程將在哪個或哪幾個CPU上執行.在一個多處理器系統中,設定CPU親合力的掩碼可能會獲得更好的效能.

一個CPU的親合力掩碼用一個cpu_set_t結構體來表示一個CPU集合,下面的幾個宏分別對這個掩碼集進行操作:
·CPU_ZERO() 清空一個集合
·CPU_SET()與CPU_CLR()分別對將一個給定的CPU號加到一個集合或者從一個集合中去掉.
·CPU_ISSET()檢查一個CPU號是否在這個集合中.

下面兩個函數就是用來設定獲取執行緒CPU親和力狀態:
·sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)
該函數設定進程為pid的這個進程,讓它執行在mask所設定的CPU上.如果pid的值為0,則表示指定的是當前進程,使當前進程執行在mask所設定的那些CPU上.第二個引數cpusetsize是mask所指定的數的長度.通常設定為sizeof(cpu_set_t).如果當前pid所指定的進程此時沒有執行在mask所指定的任意一個CPU上,則該指定的進程會從其它CPU上遷移到mask的指定的一個CPU上執行.
·sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)
該函數獲得pid所指示的進程的CPU位掩碼,並將該掩碼返回到mask所指向的結構中.即獲得指定pid當前可以執行在哪些CPU上.同樣,如果pid的值為0.也表示的是當前進程

cpu_set_t的定義 

# define __CPU_SETSIZE 1024 
# define __NCPUBITS (8 * sizeof (__cpu_mask)) 
typedef unsigned long int __cpu_mask; 
# define __CPUELT(cpu) ((cpu) / __NCPUBITS) 
# define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS)) 
typedef struct 

__cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS]; 
} cpu_set_t; 

# define __CPU_ZERO(cpusetp)  
do {  
unsigned int __i;  
cpu_set_t *__arr = (cpusetp);  
for (__i = 0; __i < sizeof (cpu_set_t) / sizeof (__cpu_mask); ++__i)  
__arr->__bits[__i] = 0;  
} while (0) 
# define __CPU_SET(cpu, cpusetp)  
((cpusetp)->__bits[__CPUELT (cpu)] |= __CPUMASK (cpu)) 
# define __CPU_CLR(cpu, cpusetp)  
((cpusetp)->__bits[__CPUELT (cpu)] &= ~__CPUMASK (cpu)) 
# define __CPU_ISSET(cpu, cpusetp)  
(((cpusetp)->__bits[__CPUELT (cpu)] & __CPUMASK (cpu)) != 0) 

測試程式碼:

#include<stdlib.h> 
#include<stdio.h> 
#include<sys/types.h> 
#include<sys/sysinfo.h> 
#include<unistd.h> 

#define __USE_GNU 
#include<sched.h> 
#include<ctype.h> 
#include<string.h> 
#include<pthread.h> 
#define THREAD_MAX_NUM 100  //1個CPU內的最多進程數 

int num=0;  //cpu中核數 
void* threadFun(void* arg)  //arg  傳遞執行緒標號(自己定義) 

        cpu_set_t mask;  //CPU核的集合 
        cpu_set_t get;  //獲取在集合中的CPU 
        int *a = (int *)arg; 
        printf("the a is:%dn",*a);  //顯示是第幾個執行緒 
        CPU_ZERO(&mask);    //置空 
        CPU_SET(*a,&mask);  //設定親和力值 
        if (sched_setaffinity(0, sizeof(mask), &mask) == -1)//設定執行緒CPU親和力 
        { 
                  printf("warning: could not set CPU affinity, continuing...n"); 
        } 
        while (1) 
        { 
                  CPU_ZERO(&get); 
                  if (sched_getaffinity(0, sizeof(get), &get) == -1)//獲取執行緒CPU親和力 
                  { 
                            printf("warning: cound not get thread affinity, continuing...n"); 
                  } 
                  int i; 
                  for (i = 0; i < num; i++) 
                  { 
                            if (CPU_ISSET(i, &get))//判斷執行緒與哪個CPU有親和力 
                            { 
                                    printf("this thread %d is running processor : %dn", i,i); 
                            } 
                  } 
        } 

        return NULL; 

int main(int argc, char* argv[]) 

        num = sysconf(_SC_NPROCESSORS_CONF);  //獲取核數 
        pthread_t thread[THREAD_MAX_NUM]; 
        printf("system has %i processor(s). n", num); 
        int tid[THREAD_MAX_NUM]; 
        int i; 
        for(i=0;i<num;i++) 
        { 
                  tid[i] = i;  //每個執行緒必須有個tid[i] 
                  pthread_create(&thread[0],NULL,threadFun,(void*)&tid[i]); 
        } 
        for(i=0; i< num; i++) 
        { 
                  pthread_join(thread[i],NULL);//等待所有的執行緒結束,執行緒為死迴圈所以CTRL+C結束 
        } 
        return 0; 

編譯命令:gcc bind.c -o bind -lpthread
執行:./bind
輸出結果:略

特別注意:

#define __USE_GNU不要寫成#define _USE_GNU
#include<pthread.h>必須寫在#define __USE_GNU之後,否則編譯會報錯

檢視你的執行緒情況可以在執行時在另一個視窗使用top -H來檢視執行緒的情況,檢視各個核上的情況請使用top命令然後按數位“1”來檢視。

Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx

本文永久更新連結地址https://www.linuxidc.com/Linux/2018-07/153190.htm


IT145.com E-mail:sddin#qq.com