2017-06-09 80 views
0

英特爾工程師寫道,我們應該使用VZEROUPPER/VZEROALL以避免在所有處理器上昂貴的過渡到非VEX狀態,包括未來的至強處理器,但不是在至強融核:https://software.intel.com/pt-br/node/704023如何檢測至強融核(騎士降落)

人們還測量並發現VZEROUPPER和VZEROALL是昂貴的上騎士降落:

36在64位模式(30個時鐘在32位模式)兩者接收指令的時鐘週期。

查看上面的鏈接。

所以我的代碼將是下面的,如果我剛使用YMM0和YMM1:

if [we are running on a Xeon Phi] 
    vpxor  ymm0,ymm0,ymm0 
    vpxor  ymm1,ymm1,ymm1 
else 
    vzeroall 
endif 

如何檢測至強融核(騎士着陸後來至強融核處理器)來實現上面的代碼?

現在,我們有以下的情況,現在有關VZEROUPPER/VZEROALL:

  1. 不需要這些說明,並在在64位模式的指令至強融核騎士降落36個時鐘週期非常昂貴(30時鐘採用32位模式)。
  2. 這些指令非常便宜,需要至強和酷睿處理器(Skylake/Kaby Lake),並且在可預見的未來將需要至強,以避免向非VEX狀態過渡的昂貴代價。

廣告材料宣稱Xeon Phi(Knights Landing)與其他Xeon處理器完全兼容。

是否有可靠的方法來檢測Xeon Phi,以避免VZEROUPPER/VZEROALL?

有一篇文章"How to detect Knights Landing AVX-512 support (Intel® Xeon Phi™ processor)" by James R., Updated February 22, 2016,但它只關注在騎士登陸中可用的特定新指令。所以VEX轉換仍然不是很清楚。

英特爾是否計劃實施CPUID位以顯示非VEX狀態是否昂貴?例如:

  • 位設置爲0 - VEX狀態轉換成本高,但VZEROUPPER/VZEROALL很便宜,應該用於清除狀態;
  • 位設置爲1 - 沒有轉換懲罰,不需要VZEROUPPER/VZEROALL。

上面提到的關於檢測騎士降落的文章建議檢查Knights Landing中介紹的AVX-512F + CD + ER + PF。

因此,代碼提示,一次檢查所有這些位,如果一切都設置,然後我們在騎士降落:

uint32_t avx2_bmi12_mask = (1 << 16) | // AVX-512F 
          (1 << 26) | // AVX-512PF 
          (1 << 27) | // AVX-512ER 
          (1 << 28); // AVX-512CD 

這本來是很好的瞭解英特爾是否計劃增加這些所有這些在不久的將來都會推出一款簡單的Xeon(非Phi)或Core處理器,所以它們也將支持Knight Landding中引入的AVX-512F + CD + ER + PF功能。

如果Xeon和Core處理器支持AVX-512F + CD + ER + PF,我們將無法區分Xeon和Xeon Phi。

請指教。

+1

你肯定在編譯時知道目標CPU,所以你可以使用預處理宏? –

+0

@PaulR,不,我們在編譯時不知道目標CPU,我們編寫的大衆市場應用程序幾乎可以在任何地方啓動,Knights Landing可以用作運行任何應用程序的主處理器。 –

+1

沒錯,但是你可以編譯優化函數的CPU特定版本,並在運行時使用調度器 - 這是英特爾在其優化庫中所做的。您的代碼將更有效率,因爲它不需要執行任何運行時檢查(除了第一次調用調度程序之外)。 –

回答

1

如果您特別想檢查是否在KNL上(而不是更一般的「我正在運行的CPU是否具有功能X?」),您可以通過查看「擴展系列」,「系列調用cpuid後,%eax == 1和%ecx == 0。「C++代碼」和「模型」字段可以完成這項工作。但是,正如其他人暗指的那樣,這是一個非常具體的測試,並且會在未來的Knights核心上失敗,所以你可能會更好地按照建議做並檢查AVX-512的功能那些不在Xeon中,所以AVX512-ER和AVX512-PF。 (當然,這些指令可能出現在未來的Xeon處理器,所以這不是在長期的保證,而且,引用凱恩斯:「從長遠來看,我們都死了」 :-))

class cpuidState 
{ 
    uint32_t orig_eax;      /* Values sent in to the cpuid instruction */ 
    uint32_t orig_ecx; 

    uint32_t eax;       /* Values received back from it. */ 
    uint32_t ebx; 
    uint32_t ecx; 
    uint32_t edx; 

    void cpuid() 
    { 
     __asm__ __volatile__("cpuid" 
          : "+a" (eax), "=b" (ebx), "+c" (ecx), "=d" (edx)); 
    } 

    void update (uint32_t eaxVal, uint32_t ecxVal) 
    { 
     orig_eax = eaxVal; 
     orig_ecx = ecxVal; 
     eax  = eaxVal; 
     ecx  = ecxVal; 
     cpuid(); 
    } 

    void ensureCorrectLeaf(uint32_t eaxVal, uint32_t ecxVal) 
    { 
     if (orig_eax != eaxVal || orig_ecx != ecxVal) 
      update (eaxVal, ecxVal); 
    } 

public: 
    cpuidState() : orig_eax (-1), orig_ecx(-1) { } 

    // Include the Extended Model in the test. Without it we see some Xeons as KNL :-(
    bool onKNL()   { ensureCorrectLeaf(1,0); return (eax & 0x0f0ff0) == 0x50670; }  
};