CPU個數、CPU核心數、CPU線程數說明(附獲取CPU邏輯核個數的代碼)

原文地址:https://www.cnblogs.com/kimsimple/p/7787018.html

CPU個數、CPU核心數、CPU線程數

 

  我們在選購電腦的時候,CPU是一個需要考慮到核心因素,因爲它決定了電腦的性能等級。CPU從早期的單核,發展到現在的雙核,多核。CPU除了核心數之外,還有線程數之說,下面文本就來解釋一下CPU的核心數與線程數的關係和區別。 

CPU個數即CPU芯片個數

CPU的核心數是指物理上,也就是硬件上存在着幾個核心。比如,雙核就是包括2個相對獨立的CPU核心單元組,四核就包含4個相對獨立的CPU核心單元組。

線程數是一種邏輯的概念,簡單地說,就是模擬出的CPU核心數。比如,可以通過一個CPU核心數模擬出2線程的CPU,也就是說,這個單核心的CPU被模擬成了一個類似雙核心CPU的功能。我們從任務管理器的性能標籤頁中看到的是兩個CPU。 比如Inte l賽揚G460是單核心,雙線程的CPU,Intel 酷睿i3 3220是雙核心 四線程,Intel 酷睿i7 4770K是四核心 八線程 ,Intel 酷睿i5 4570是四核心 四線程等等。 對於一個CPU,線程數總是大於或等於核心數的。一個核心最少對應一個線程,但通過超線程技術,一個核心可以對應兩個線程,也就是說它可以同時運行兩個線程。 

CPU的線程數概念僅僅只針對Intel的CPU纔有用,因爲它是通過Intel超線程技術來實現的,最早應用在Pentium4上。如果沒有超線程技術,一個CPU核心對應一個線程。所以,對於AMD的CPU來說,只有核心數的概念,沒有線程數的概念。 

CPU之所以要增加線程數,是源於多任務處理的需要。線程數越多,越有利於同時運行多個程序,因爲線程數等同於在某個瞬間CPU能同時並行處理的任務數。 因此,線程數是一種邏輯的概念,簡單地說,就是模擬出的 CPU 核心數。一個核心最少對應一個線程,但英特爾有個超線程技術可以把一個物理線程模擬出兩個線程來用,充分發揮 CPU 性能,即一個核心可以有兩個到多個線程。

設計決定,intel給他的x86設計了邏輯線程=2*物理核心數,ibm的power8是邏輯線程=8*物理核心數

Hyper-Threading,超線程

 


 

多核CPU

 多核心cpu主要分原生多核和封裝多核。
  原生多核指的是真正意義上的多核,最早由AMD提出,每個核心之間都是完全獨立的,都擁有自己的前端總線,不會造成衝突,即使在高負載狀況下,每個核心都能保證自己的性能不受太大的影響,通俗的說,原生多核的抗壓能力強,但是需要先進的工藝,每擴展一個核心都需要很多的研發時間。
  封裝多核是隻把多個核心直接封裝在一起,比如Intel早期的PD雙核系列,就是把兩個單核直接封裝在一起,但兩核心只能共同擁有一條前端總線,在兩個核心滿載時,兩個核心會爭搶前端總線,導致性能大幅度下降,所以早期的PD被扣上了“高頻低能”的帽子,要提高封裝多核的性能,在多任務的高壓下儘量減少性能損失,只能不斷的擴大前端總線的總體大小,來彌補多核心爭搶資源帶來的性能損失,但這樣做只能在一定程度上彌補性能的不足,和原生的比起來還是差了很多,而且後者成本比較高,優點在於多核心的發展要比原生快的多。

 

核心(Die)又稱爲內核,是CPU最重要的組成部分。CPU中心那塊隆起的芯片就是核心,是由單晶硅以一定的生產工藝製造出來的,CPU所有的計算、接受/存儲命令、處理數據都由核心執行。各種CPU核心都具有固定的邏輯結構一級緩存二級緩存、執行單元、指令級單元和總線接口邏輯單元都會有科學的佈局。

雙內核應該具備兩個物理上的運算內核

HT技術超線程技術,是造就了PENTIUM 4的一個輝煌時代的武器,儘管它被評爲失敗的技術,但是卻對P4起一定推廣作用,雙核心處理器是全新推出的處理器類別;HT技術是在處理器實現2個邏輯處理器,是充分利用處理器資源,雙核心處理器是集成2個物理核心,是實際意義上的雙核心處理器。

多核心處理器(英語:Multi-core processor),又稱多核心微處理器,是在單個計算組件中,加入兩個或以上的獨立實體中央處理單元(簡稱核心,英語:Core)。這些核心可以分別獨立地運行程序指令,利用並行計算的能力加快程序的運行速度。只有兩個核心的處理器,稱爲雙核心處理器(dual-core processor)。“多核心”通常是對於中央處理器(Central Processing Unit,CPU)而論的,但是某些時候也指數字信號處理器(DSP)和系統芯片(SoC)。

通常,把將兩個或更多獨立處理器封裝在一個單一集成電路(IC)中的方案稱爲多核心處理器;而封裝在不同IC中的獨立處理器形成的計算機系統被稱爲多處理器

多核心處理器!=多處理器

多核心處理器可以在不將每個核心分別獨立物理封裝的情況下進行多任務處理(線程級併發處理Thread-Level Parallelism,TLP),這種形式的TLP通常被認爲是芯片級多處理)。

 


單核多CPU與多核單CPU

一臺計算機的處理器部分的架構

單核多CPU,那麼每一個CPU都需要有較爲獨立的電路支持,有自己的Cache,而他們之間通過板上的總線進行通信。(一致性問題)

假如在這樣的架構上,我們要跑一個多線程的程序(常見典型情況),不考慮超線程,那麼每一個線程就要跑在一個獨立的CPU上,線程間的所有協作都要走總線,而共享的數據更是有可能要在好幾個Cache裏同時存在。這樣的話,總線開銷相比較而言是很大的,怎麼辦?那麼多Cache,即使我們不心疼存儲能力的浪費,一致性怎麼保證?

多核單CPU,那麼我們只需要一套芯片組,一套存儲,多核之間通過芯片內部總線進行通信,共享使用內存。在這樣的架構上,如果我們跑一個多線程的程序,那麼線程間通信將比上一種情形更快。

 

多個CPU常見於分佈式系統,用於普通消費級市場的不多,多用於cluster,雲計算平臺什麼的。多CPU架構最大的瓶頸就是I/O,尤其是各個CPU之間的通訊,低成本的都用100M以太網做,稍微好一點的用1000M以太網,再好的就用光纖等等,但無論如何速度和通量都比不上主板的主線。所以多CPU適用於大計算量,對速度(時間)不(太)敏感的任務,比如一些工程建模,或者像SATI找外星人這種極端的,跑上幾千年都不着急的。而且多CPU架構更簡單清晰,可以用消費級產品簡單做數量堆疊,成本上有優勢。而多核單CPU則適合對通訊I/O速度要求較快的應用,(相同核數量下)成本上也高一些,好像只有在超級計算機裏會用到以萬爲單位的核心數,普通消費級產品也就是到16核封頂了,因爲成本控制的原因。

 

 


附 - 獲取CPU邏輯核個數的代碼

在Windows中,在cmd命令中輸入“wmic”,然後在出現的新窗口中分別輸入“cpu get Name”,“cpu get NumberOfCores”,“cpu get NumberOfLogicalProcessors”即可查看物理CPU數、CPU核心數、線程數。
如下圖所示:

Name:表示物理CPU數 
NumberOfCores:表示CPU核心數 
NumberOfLogicalProcessors:表示CPU線程數
註釋:VM虛擬機中的CPU選擇的核心數實際是代表線程數。

輸入“cpu get *”也可

2.在cmd命令中輸入“systeminfo”,以下信息表示物理CPU有兩個

   

 

另外,獲取CPU邏輯核數(線程數),使用GetLogicalProcessorInformation API(url:https://docs.microsoft.com/zh-cn/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformation),但該函數只支持到XP SP3版本,之前的windows系統則不支持!最新在線MSDN上的給的示例代碼:(VS2008自帶的MSDN上的示例代碼較老,使用在線最新版本的MSDN上的代碼)

#include <windows.h>
#include <malloc.h>    
#include <stdio.h>
#include <tchar.h>

typedef BOOL (WINAPI *LPFN_GLPI)(
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, 
    PDWORD);


// Helper function to count set bits in the processor mask.
DWORD CountSetBits(ULONG_PTR bitMask)
{
    DWORD LSHIFT = sizeof(ULONG_PTR)*8 - 1;
    DWORD bitSetCount = 0;
    ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;    
    DWORD i;
    
    for (i = 0; i <= LSHIFT; ++i)
    {
        bitSetCount += ((bitMask & bitTest)?1:0);
        bitTest/=2;
    }

    return bitSetCount;
}

int _cdecl _tmain ()
{
    LPFN_GLPI glpi;
    BOOL done = FALSE;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
    DWORD returnLength = 0;
    DWORD logicalProcessorCount = 0;
    DWORD numaNodeCount = 0;
    DWORD processorCoreCount = 0;
    DWORD processorL1CacheCount = 0;
    DWORD processorL2CacheCount = 0;
    DWORD processorL3CacheCount = 0;
    DWORD processorPackageCount = 0;
    DWORD byteOffset = 0;
    PCACHE_DESCRIPTOR Cache;

    glpi = (LPFN_GLPI) GetProcAddress(
                            GetModuleHandle(TEXT("kernel32")),
                            "GetLogicalProcessorInformation");
    if (NULL == glpi) 
    {
        _tprintf(TEXT("\nGetLogicalProcessorInformation is not supported.\n"));
        return (1);
    }

    while (!done)
    {
        DWORD rc = glpi(buffer, &returnLength);

        if (FALSE == rc) 
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
            {
                if (buffer) 
                    free(buffer);

                buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(
                        returnLength);

                if (NULL == buffer) 
                {
                    _tprintf(TEXT("\nError: Allocation failure\n"));
                    return (2);
                }
            } 
            else 
            {
                _tprintf(TEXT("\nError %d\n"), GetLastError());
                return (3);
            }
        } 
        else
        {
            done = TRUE;
        }
    }

    ptr = buffer;

    while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) 
    {
        switch (ptr->Relationship) 
        {
        case RelationNumaNode:
            // Non-NUMA systems report a single record of this type.
            numaNodeCount++;
            break;

        case RelationProcessorCore:
            processorCoreCount++;

            // A hyperthreaded core supplies more than one logical processor.
            logicalProcessorCount += CountSetBits(ptr->ProcessorMask);
            break;

        case RelationCache:
            // Cache data is in ptr->Cache, one CACHE_DESCRIPTOR structure for each cache. 
            Cache = &ptr->Cache;
            if (Cache->Level == 1)
            {
                processorL1CacheCount++;
            }
            else if (Cache->Level == 2)
            {
                processorL2CacheCount++;
            }
            else if (Cache->Level == 3)
            {
                processorL3CacheCount++;
            }
            break;

        case RelationProcessorPackage:
            // Logical processors share a physical package.
            processorPackageCount++;
            break;

        default:
            _tprintf(TEXT("\nError: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value.\n"));
            break;
        }
        byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
        ptr++;
    }

    _tprintf(TEXT("\nGetLogicalProcessorInformation results:\n"));
    _tprintf(TEXT("Number of NUMA nodes: %d\n"), 
             numaNodeCount);
    _tprintf(TEXT("Number of physical processor packages: %d\n"), 
             processorPackageCount);
    _tprintf(TEXT("Number of processor cores: %d\n"), 
             processorCoreCount);
    _tprintf(TEXT("Number of logical processors: %d\n"), 
             logicalProcessorCount);
    _tprintf(TEXT("Number of processor L1/L2/L3 caches: %d/%d/%d\n"), 
             processorL1CacheCount,
             processorL2CacheCount,
             processorL3CacheCount);
    
    free(buffer);

    return 0;
}

對於XP SP3之前的系統,則只能使用GetSystemInfo API來獲取了。現在基本上都是XPSP3及以上的系統了。

另外,在MSDN上對SYSTEMINFO結構體的說明中也提到,要獲取CPU邏輯核的個數,要使用GetLogicalProcessorInformation:

結構體中關於dwNumberOfProcessors字段的說明:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章