GNU/Linux >> Znalost Linux >  >> Linux

Zjistěte, zda má procesor RDTSCP v době kompilace

GCC definuje mnoho maker, která v době kompilace určí, zda je konkrétní funkce podporována mikroarchitekturou zadanou pomocí -march . Celý seznam najdete ve zdrojovém kódu zde. Je jasné, že GCC takové makro pro RDTSCP nedefinuje (nebo dokonce RDTSC na to přijde). Procesory, které podporují RDTSCP jsou uvedeny v:Jaký je typ gcc cpu, který zahrnuje podporu pro RDTSCP?.

Takže si můžete vytvořit svůj vlastní (potenciálně neúplný) seznam mikroarchitektur, které podporují RDTSCP . Poté napište sestavení skriptu, který zkontroluje argument předaný do -march a zjistěte, zda je v seznamu. Pokud ano, definujte makro, například __RDTSCP__ a použijte jej ve svém kódu. Předpokládám, že i když je váš seznam neúplný, nemělo by to ohrozit správnost vašeho kódu.

Bohužel se zdá, že datasheety Intelu neuvádějí, zda konkrétní procesor podporuje RDTSCP i když diskutují o dalších funkcích, jako je AVX2.

Jedním z potenciálních problémů je, že neexistuje žádná záruka, že každý jeden procesor, který implementuje konkrétní mikroarchitekturu, jako je Skylake, podporuje RDTSCP . Nejsem si však vědom takových výjimek.

Související:Jaký je typ cpu gcc, který zahrnuje podporu pro RDTSCP?.

Zjištění podpory RDTSCP za běhu , lze následující kód použít na kompilátorech podporujících rozšíření GNU (GCC, clang, ICC), na jakémkoli x86 OS. cpuid.h je dodáván s kompilátorem, nikoli s OS.

#include <cpuid.h>

int rdtscp_supported(void) {
    unsigned a, b, c, d;
    if (__get_cpuid(0x80000001, &a, &b, &c, &d) && (d & (1<<27)))
    {
        // RDTSCP is supported.
        return 1;
    }
    else
    {
        // RDTSCP is not supported.
        return 0;
    }
}

__get_cpuid() spustí CPUID dvakrát:jednou pro kontrolu maximální úrovně, jednou se zadanou hodnotou listu. Vrací false, pokud požadovaná úroveň ani není k dispozici, proto je součástí && výraz. Pravděpodobně to nebudete chtít používat pokaždé před rdtscp, jen jako inicializátor pro proměnnou, pokud to není jen jednoduchý jednorázový program. Podívejte se na to v průzkumníku kompilátoru Godbolt.

Pro MSVC viz Jak zjistit podporu rdtscp ve Visual C++? pro kód využívající jeho vnitřní.

Pro některé funkce CPU, o kterých GCC ví, můžete použít __builtin_cpu_supports pro kontrolu bitmapy funkce, která je inicializována na začátku spouštění.

// unfortunately no equivalent for RDTSCP
int sse42_supported() {
    return __builtin_cpu_supports("sse4.2");
}

Poznámka editora:https://gcc.gnu.org/wiki/DontUseInlineAsm . Tato odpověď po dlouhou dobu nebyla bezpečná a později byla upravena tak, aby se nedala ani zkompilovat, a přitom byla stále nebezpečná (obtěžování RAX a vytváření "a" omezení nesplnitelné, a přitom stále chybí clobbery v registrech, které CPUID zapisuje). Použijte vnitřní podstatu v jiné odpovědi. (Ale opravil jsem vložený asm v tomto, aby byl bezpečný a správný, pro případ, že by to někdo zkopíroval/vložil nebo se chtěl naučit, jak správně používat omezení a clobbery.)

Poté, co jsem trochu více prozkoumal na základě návrhů od @Jasona, mám nyní řešení za běhu (stále ne řešení v době kompilace), abych zjistil, zda RDTSCP existuje kontrolou 28. bitu (viz výstupní bitmapa) z cpuid instrukce s 0x80000001 jako vstup v EAX .

int if_rdtscp() {
    unsigned int edx;
    unsigned int eax = 0x80000001;
#ifdef __GNUC__              // GNU extended asm supported
    __asm__ (     // doesn't need to be volatile: same EAX input -> same outputs
     "CPUID\n\t"
    : "+a" (eax),         // CPUID writes EAX, but we can't declare a clobber on an input-only operand.
      "=d" (edx)
    : // no read-only inputs
    : "ecx", "ebx");      // CPUID writes E[ABCD]X, declare clobbers

    // a clobber on ECX covers the whole RCX, so this code is safe in 64-bit mode but is portable to either.

#else // Non-gcc/g++ compilers.
    // To-do when needed
#endif
    return (edx >> 27) & 0x1;
}

Pokud to nefunguje v 32bitovém kódu PIC kvůli clobberu EBX, pak 1. přestaňte používat 32bitový PIC, protože je neefektivní v porovnání s 64bitovým PIC nebo vs. -fno-pie -no-pie spustitelné soubory. 2. získejte novější GCC, který umožňuje clobbery EBX dokonce i v 32bitovém kódu PIC, vydávající další pokyny k uložení/obnovení EBX nebo čehokoli, co je potřeba. 3. použijte verzi intrinsics (která by vám měla toto obejít).

Zatím mi jsou s kompilátory GNU v pořádku, ale pokud to někdo potřebuje udělat pod MSVC, pak je vnitřní způsob, jak to zkontrolovat, jak je vysvětleno zde.


Linux
  1. Stavy procesu Linuxu

  2. Detekce 64bitové kompilace v C

  3. Jak zjistit, zda má soubor v Bash kusovník UTF-8?

  1. Jak zjistit, zda byl VT-X zapnutý v BIOSu?

  2. Čas provedení více příkazů

  3. Jak dlouho můj systém Linux běží?

  1. Jak říci Rsync, aby uchoval časové razítko v souborech, když má zdrojový strom připojený bod?

  2. Jak zjistit grafický procesor Intel?

  3. Nejlepší způsob, jak zkompilovat jádro pro procesor I7?