Compute Library
 21.02
arm_compute::utils::cpu Namespace Reference

Functions

void get_cpu_configuration (CPUInfo &cpuinfo)
 This function will try to detect the CPU configuration on the system and will fill the cpuinfo object accordingly to reflect this. More...
 
unsigned int get_threads_hint ()
 Some systems have both big and small cores, this fuction computes the minimum number of cores that are exactly the same on the system. More...
 

Function Documentation

◆ get_cpu_configuration()

void get_cpu_configuration ( CPUInfo cpuinfo)

This function will try to detect the CPU configuration on the system and will fill the cpuinfo object accordingly to reflect this.

Parameters
[out]cpuinfoCPUInfo to be used to hold the system's cpu configuration.

Definition at line 359 of file CPUUtils.cpp.

References ARM_COMPUTE_UNUSED, arm_compute::GENERIC, HWCAP_ASIMDDP, HWCAP_ASIMDHP, HWCAP_CPUID, CPUInfo::set_cpu_model(), CPUInfo::set_cpu_num(), CPUInfo::set_dotprod(), and CPUInfo::set_fp16().

Referenced by DeviceProperties::DeviceProperties(), and IScheduler::IScheduler().

360 {
361 #if !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))
362  bool cpuid = false;
363  bool hwcaps_fp16_support = false;
364  bool hwcaps_dot_support = false;
365 
366  const uint32_t hwcaps = getauxval(AT_HWCAP);
367 
368  if((hwcaps & HWCAP_CPUID) != 0)
369  {
370  cpuid = true;
371  }
372 
373  if((hwcaps & HWCAP_ASIMDHP) != 0)
374  {
375  hwcaps_fp16_support = true;
376  }
377 
378 #if defined(__aarch64__)
379  if((hwcaps & HWCAP_ASIMDDP) != 0)
380  {
381  hwcaps_dot_support = true;
382  }
383 #endif /* defined(__aarch64__) */
384 
385  const unsigned int max_cpus = get_max_cpus();
386  cpuinfo.set_cpu_num(max_cpus);
387  std::vector<CPUModel> percpu(max_cpus, CPUModel::GENERIC);
388  if(cpuid)
389  {
390  populate_models_cpuid(percpu);
391  }
392  else
393  {
394  populate_models_cpuinfo(percpu);
395  }
396  int j(0);
397  // Update dot product and FP16 support if one of the CPUs support these features
398  // We assume that the system does not have mixed architectures
399  bool one_supports_dot = false;
400  bool one_supports_fp16 = false;
401  for(const auto &v : percpu)
402  {
403  one_supports_dot = one_supports_dot || model_supports_dot(v);
404  one_supports_fp16 = one_supports_fp16 || model_supports_fp16(v);
405  cpuinfo.set_cpu_model(j++, v);
406  }
407  cpuinfo.set_dotprod(one_supports_dot || hwcaps_dot_support);
408  cpuinfo.set_fp16(one_supports_fp16 || hwcaps_fp16_support);
409 #else /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */
410  ARM_COMPUTE_UNUSED(cpuinfo);
411 #endif /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */
412 }
#define HWCAP_ASIMDDP
Definition: CPUUtils.cpp:61
#define HWCAP_CPUID
Definition: CPUUtils.cpp:57
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
void set_cpu_model(unsigned int cpuid, CPUModel model)
Set the cpumodel for a given cpu core.
Definition: CPPTypes.cpp:45
#define HWCAP_ASIMDHP
Definition: CPUUtils.cpp:53
void set_dotprod(const bool dotprod)
Set dot product support.
Definition: CPPTypes.cpp:40
void set_fp16(const bool fp16)
Set fp16 support.
Definition: CPPTypes.cpp:35
void set_cpu_num(unsigned int cpu_count)
Set max number of cpus.
Definition: CPPTypes.cpp:97

◆ get_threads_hint()

unsigned int get_threads_hint ( )

Some systems have both big and small cores, this fuction computes the minimum number of cores that are exactly the same on the system.

To maximize performance the library attempts to process workloads concurrently using as many threads as big cores are available on the system.

Returns
The minumum number of common cores.

Definition at line 414 of file CPUUtils.cpp.

References ARM_COMPUTE_ERROR_ON_MSG, and ARM_COMPUTE_UNUSED.

Referenced by IScheduler::IScheduler().

415 {
416  unsigned int num_threads_hint = 1;
417 
418 #if !defined(BARE_METAL)
419  std::map<std::string, unsigned int> cpu_part_occurrence_map;
420 
421  // CPU part regex
422  regex_t cpu_part_rgx;
423  memset(&cpu_part_rgx, 0, sizeof(regex_t));
424  int ret_status = regcomp(&cpu_part_rgx, R"(.*CPU part.+/?\:[[:space:]]+([[:alnum:]]+).*)", REG_EXTENDED);
425  ARM_COMPUTE_UNUSED(ret_status);
426  ARM_COMPUTE_ERROR_ON_MSG(ret_status != 0, "Regex compilation failed.");
427 
428  // Read cpuinfo and get occurrence of each core
429  std::ifstream cpuinfo;
430  cpuinfo.open("/proc/cpuinfo", std::ios::in);
431  if(cpuinfo.is_open())
432  {
433  std::string line;
434  while(bool(getline(cpuinfo, line)))
435  {
436  std::array<regmatch_t, 2> match;
437  ret_status = regexec(&cpu_part_rgx, line.c_str(), 2, match.data(), 0);
438  if(ret_status == 0)
439  {
440  std::string cpu_part = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
441  if(cpu_part_occurrence_map.find(cpu_part) != cpu_part_occurrence_map.end())
442  {
443  cpu_part_occurrence_map[cpu_part]++;
444  }
445  else
446  {
447  cpu_part_occurrence_map[cpu_part] = 1;
448  }
449  }
450  }
451  }
452  regfree(&cpu_part_rgx);
453 
454  // Get min number of threads
455  auto min_common_cores = std::min_element(cpu_part_occurrence_map.begin(), cpu_part_occurrence_map.end(),
456  [](const std::pair<std::string, unsigned int> &p1, const std::pair<std::string, unsigned int> &p2)
457  {
458  return p1.second < p2.second;
459  });
460 
461  // Set thread hint
462  num_threads_hint = cpu_part_occurrence_map.empty() ? std::thread::hardware_concurrency() : min_common_cores->second;
463 #endif /* !defined(BARE_METAL) */
464 
465  return num_threads_hint;
466 }
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
Definition: Error.h:456