Как Обнаружить Количество Физических процессоров / Ядра в Windows, Mac и Linux

Попробуйте это

=SUMPRODUCT(--(LEFT(A1:A100,3)=LEFT(A1,3)))
44
задан Royi 7 October 2019 в 07:49
поделиться

5 ответов

В Windows, существуют GetLogicalProcessorInformation и GetLogicalProcessorInformationEx доступны для Windows XP SP3 или более старого и Windows 7 + соответственно. Различие - то, что GetLogicalProcessorInformation не поддерживает установки больше чем с 64 логическими ядрами, которые могли бы быть важны для установок сервера, но можно всегда отступать к GetLogicalProcessorInformation, если Вы находитесь на XP. Использование в качестве примера для GetLogicalProcessorInformationEx ( источник ):

PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX buffer = NULL;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ptr = NULL;
BOOL rc;
DWORD length = 0;
DWORD offset = 0;
DWORD ncpus = 0;
DWORD prev_processor_info_size = 0;
for (;;) {
    rc = psutil_GetLogicalProcessorInformationEx(
            RelationAll, buffer, &length);
    if (rc == FALSE) {
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
            if (buffer) {
                free(buffer);
            }
            buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)malloc(length);
            if (NULL == buffer) {
                return NULL;
            }
        }
        else {
            goto return_none;
        }
    }
    else {
        break;
    }
}
ptr = buffer;
while (offset < length) {
    // Advance ptr by the size of the previous
    // SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX struct.
    ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)\
        (((char*)ptr) + prev_processor_info_size);

    if (ptr->Relationship == RelationProcessorCore) {
        ncpus += 1;
    }

    // When offset == length, we've reached the last processor
    // info struct in the buffer.
    offset += ptr->Size;
    prev_processor_info_size = ptr->Size;
}

free(buffer);
if (ncpus != 0) {
    return ncpus;
}
else {
    return NULL;
}

return_none:
if (buffer != NULL)
    free(buffer);
return NULL;

На Linux, анализируя /proc/cpuinfo мог бы помочь.

0
ответ дан 26 November 2019 в 22:01
поделиться

Решение только для Windows, описанное здесь:

GetLogicalProcessorInformation

для linux, файл /proc/cpuinfo. Я не работаю под linux сейчас, поэтому не могу дать вам более подробную информацию. Вы можете подсчитать физические/логические экземпляры процессоров. Если количество логических в два раза больше физических, то у вас включен HT (верно только для x86).

15
ответ дан 26 November 2019 в 22:01
поделиться

Я не знаю, что все три предоставляют информацию одинаково, но если вы можете с уверенностью предположить, что ядро ​​NT будет сообщать информацию об устройстве в соответствии со стандартом POSIX (который NT предположительно поддерживает), тогда вы можете работать с этим стандартом.

Тем не менее, различия в управлении устройствами часто упоминаются как один из камней преткновения на пути кроссплатформенной разработки. В лучшем случае я бы реализовал это в виде трех логических цепочек, я бы не пытался написать один фрагмент кода для равномерного управления всеми платформами.

Хорошо, все, что предполагает C ++. Что касается ASM, я полагаю, вы будете работать только на процессорах x86 или amd64? Вам по-прежнему понадобятся два пути ветвления, по одному для каждой архитектуры, и вам нужно будет тестировать Intel отдельно от AMD (IIRC), но в целом вы просто проверяете CPUID. Это то, что вы пытаетесь найти? CPUID из ASM на процессорах семейства Intel / AMD?

0
ответ дан 26 November 2019 в 22:01
поделиться

Обратите внимание на это, здесь указано не количество физических ядер, как задумано, а количество логических ядер.

Если вы можете использовать C ++ 11 (спасибо комментарию alfC ниже):

#include <iostream>
#include <thread>

int main() {
    std::cout << std::thread::hardware_concurrency() << std::endl;
    return 0;
}

В противном случае, возможно, вам подойдет библиотека Boost. Тот же код, но другой, как указано выше. Включите вместо .

17
ответ дан 26 November 2019 в 22:01
поделиться
​​

РЕДАКТИРОВАТЬ: Это больше не на 100% правильно из-за непрекращающейся путаницы Intel.

Насколько я понимаю, вопрос заключается в том, что вы спрашиваете, как определить количество ядер ЦП по сравнению с потоками ЦП, что отличается от определения количества логических и физических ядер в системе. Ядра ЦП часто не считаются ОС физическими ядрами, если у них нет собственного пакета или они не умирают. Таким образом, ОС будет сообщать, что, например, Core 2 Duo имеет 1 физический и 2 логических процессора, а Intel P4 с гиперпотоками будет сообщаться точно так же, даже если 2 гиперпотока против 2 ядер ЦП - это очень разные вещи с точки зрения производительности.

Я боролся с этим, пока не собрал воедино решение ниже, которое, как мне кажется, работает как для процессоров AMD, так и для Intel. Насколько мне известно, и я могу ошибаться, у AMD еще нет потоков ЦП, но они предоставили способ их обнаружения, который, как я полагаю, будет работать на будущих процессорах AMD, которые могут иметь потоки ЦП.

Вкратце, вот шаги с использованием инструкции CPUID:

  1. Определить поставщика ЦП с помощью функции 0 CPUID
  2. Проверить бит 28 HTT в функциях ЦП EDX из функции CPUID 1
  3. Получить количество логических ядер из EBX [23:16] из функции CPUID 1
  4. Получить фактическое количество ядер ЦП без потоковой передачи
    1. Если vendor == 'GenuineIntel', это 1 плюс EAX [31:26] из функции CPUID 4
    2. Если vendor == 'AuthenticAMD', это 1 плюс ECX [7: 0] из функции CPUID 0x80000008

Звучит сложно, но вот, надеюсь, независимая от платформы программа на C ++, которая справится с этой задачей:

#include <iostream>
#include <string>

using namespace std;


void cpuID(unsigned i, unsigned regs[4]) {
#ifdef _WIN32
  __cpuid((int *)regs, (int)i);

#else
  asm volatile
    ("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
     : "a" (i), "c" (0));
  // ECX is set to zero for CPUID function 4
#endif
}


int main(int argc, char *argv[]) {
  unsigned regs[4];

  // Get vendor
  char vendor[12];
  cpuID(0, regs);
  ((unsigned *)vendor)[0] = regs[1]; // EBX
  ((unsigned *)vendor)[1] = regs[3]; // EDX
  ((unsigned *)vendor)[2] = regs[2]; // ECX
  string cpuVendor = string(vendor, 12);

  // Get CPU features
  cpuID(1, regs);
  unsigned cpuFeatures = regs[3]; // EDX

  // Logical core count per CPU
  cpuID(1, regs);
  unsigned logical = (regs[1] >> 16) & 0xff; // EBX[23:16]
  cout << " logical cpus: " << logical << endl;
  unsigned cores = logical;

  if (cpuVendor == "GenuineIntel") {
    // Get DCP cache info
    cpuID(4, regs);
    cores = ((regs[0] >> 26) & 0x3f) + 1; // EAX[31:26] + 1

  } else if (cpuVendor == "AuthenticAMD") {
    // Get NC: Number of CPU cores - 1
    cpuID(0x80000008, regs);
    cores = ((unsigned)(regs[2] & 0xff)) + 1; // ECX[7:0] + 1
  }

  cout << "    cpu cores: " << cores << endl;

  // Detect hyper-threads  
  bool hyperThreads = cpuFeatures & (1 << 28) && cores < logical;

  cout << "hyper-threads: " << (hyperThreads ? "true" : "false") << endl;

  return 0;
}

Я еще не тестировал это на Windows или OSX, но она должна работать, поскольку инструкция CPUID действительна на машинах i686. Очевидно, это не сработает для PowerPC, но тогда и у них нет гиперпотоков.

Вот результат на нескольких разных машинах Intel:

Intel (R) Core (TM) 2 Duo CPU T7500 @ 2,20 ГГц:

 logical cpus: 2
    cpu cores: 2
hyper-threads: false

Intel (R) Core (TM) 2 Quad CPU Q8400 @ 2,66 ГГц:

 logical cpus: 4
    cpu cores: 4
hyper-threads: false

Intel (R) Xeon (R) CPU E5520 @ 2,27 ГГц (с x2 пакетами физических процессоров):

 logical cpus: 16
    cpu cores: 8
hyper-threads: true

Intel (R) Pentium (R) 4 CPU 3,00 ГГц:

 logical cpus: 2
    cpu cores: 1
hyper-threads: true
25
ответ дан 26 November 2019 в 22:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: