geopm::PlatformTopo(3) – platform topology information

Namespaces

The PlatformTopo class and platform_topo() singleton accessor function are members of namespace geopm, but the full names, geopm::PlatformTopo and geopm::platform_topo(), have been abbreviated in this manual. Similarly, the std:: namespace specifier has been omitted from the interface definitions for the following standard types: std::vector, std::string, and std::set, to enable better rendering of this manual.

Note that PlatformTopo class is an abstract base class that the user interacts with. The concrete implementation, PlatformTopoImp, is hidden by the singleton accessor.

Synopsis

#include <geopm/PlatformTopo.hpp>

Link with -lgeopmd

PlatformTopo &platform_topo(void);

int PlatformTopo::num_domain(int domain_type) const = 0;

int PlatformTopo::domain_idx(int domain_type,
                             int cpu_idx) const = 0;

bool PlatformTopo::is_nested_domain(int inner_domain,
                                    int outer_domain) const = 0;

set<int> PlatformTopo::domain_nested(int inner_domain,
                                     int outer_domain,
                                     int outer_idx) const = 0;

static string PlatformTopo::domain_type_to_name(int domain_type);

static int PlatformTopo::domain_name_to_type(const string &domain_name);

static void PlatformTopo::create_cache(void);

Description

This class describes the number and arrangement of cores, sockets, logical CPUs, memory banks, and other components. This information is used when calling methods of the geopm::PlatformIO(3) interface. The topology of the current platform is available using the singleton geopm::platform_topo(). The remaining methods are accessed through this singleton.

Most methods in the PlatformTopo interface return or require as an argument an integer domain type, used to refer to different parts of the system topology where signals and controls are applicable. Each domain is defined by a type and an index. The domain type is a value from the geopm_domain_e enum, and the domain index enumerates the devices of that type available on the system. Refer to the list of domain types in in geopm_topo(3). The domains are effectively hierarchical and the PlatformTopo::domain_nested() method can be used to explore which domains are nested within a specified outer domain. Each domain, specified by pairing a domain type and a domain index, is related to a specific set of Linux logical CPUs which reside at the leaves of the hierarchy. These are the set of CPUs that can most efficiently issue instructions to read signals from or write controls to the domain.

Singleton Accessor

platform_topo()

Returns the singleton accessor for the PlatformTopo interface.

Class Methods

num_domain()

Number of domains on the platform of a particular domain_type. Refer to the list of domain types in geopm_topo(3).

domain_idx()

Get the domain index for a particular domain_type that contains the given Linux logical CPU with index cpu_idx.

is_nested_domain()

Check if inner_domain is contained within outer_domain. GEOPM_DOMAIN_BOARD is the outermost domain representing the entire node. All other domains are contained within board. GEOPM_DOMAIN_CORE, GEOPM_DOMAIN_CPU, GEOPM_DOMAIN_PACKAGE_INTEGRATED_MEMORY, and GEOPM_DOMAIN_PACKAGE_INTEGRATED_GPU are contained within package. GEOPM_DOMAIN_CPU is contained within GEOPM_DOMAIN_CORE. The following outline summarizes the hierarchy of containing domains, where each domain is also contained in parents of its parent domain.

`GEOPM_DOMAIN_BOARD`
 +---`GEOPM_DOMAIN_PACKAGE`
      +---`GEOPM_DOMAIN_CORE`
           +---`GEOPM_DOMAIN_CPU`
      +---`GEOPM_DOMAIN_PACKAGE_INTEGRATED_MEMORY`
      +---`GEOPM_DOMAIN_PACKAGE_INTEGRATED_NIC`
      +---`GEOPM_DOMAIN_PACKAGE_INTEGRATED_GPU`
 +---`GEOPM_DOMAIN_MEMORY`
 +---`GEOPM_DOMAIN_NIC`
 +---`GEOPM_DOMAIN_GPU`
domain_nested()

Returns the set of smaller domains of type inner_domain contained with a larger domain of type outer_domain at outer_idx. If the inner domain is not the same as or contained within the outer domain, it throws an exception.

domain_type_to_name()

Convert a domain_type integer to a string. These strings are used by the geopmread(1) and geopmwrite(1) tools.

domain_name_to_type()

Convert a domain_name string to the corresponding integer domain type. This method is the inverse of domain_type_to_name().

create_cache()

Create cache file in tmpfs that can be read instead of popen() call.

Examples

The following example program queries the PlatformTopo to calculate various information of interest about the platform.

#include <iostream>

#include <geopm/PlatformTopo.hpp>

using geopm::PlatformTopo;

int main() {
    const PlatformTopo &topo = geopm::platform_topo();

    int num_cores = topo.num_domain(GEOPM_DOMAIN_CORE);
    int num_cpus = topo.num_domain(GEOPM_DOMAIN_CPU);
    int num_pkgs = topo.num_domain(GEOPM_DOMAIN_PACKAGE);

    // Print counts of various domains
    std::cout << "Domain      Count      " << std::endl;
    std::cout << "-----------------------" << std::endl;
    std::cout << "cores       " << num_cores << std::endl;
    std::cout << "packages    " << num_pkgs << std::endl;
    std::cout << "core/pkg    " << num_cores / num_pkgs << std::endl;
    std::cout << "cpu/core    " << num_cpus / num_cores << std::endl;
    std::cout << "cpu/pkg     " << num_cpus / num_pkgs << std::endl;
}

For example, when run on a system with 2 sockets, 4 cores per socket, and 3 hyperthreads per core, the following would be printed to standard output:

Domain      Count
-----------------------
cores       8
packages    2
core/pkg    4
cpu/core    3
cpu/pkg     12

This loop, inserted into the above program, prints the Linux CPUs on each package:

for (int pkg_idx = 0; pkg_idx < num_pkgs; ++pkg_idx) {
    std::cout << "CPUs on package " << pkg_idx << ": ";
    std::set<int> cpus = topo.domain_nested(GEOPM_DOMAIN_CPU, GEOPM_DOMAIN_PACKAGE, pkg_idx);
    for(auto pcpu : cpus) {
        std::cout << pcpu << " ";
    }
    std::cout << std::endl;
}

The output for the same system would be:

CPUs on package 0: 0 1 2 3 8 9 10 11 16 17 18 19
CPUs on package 1: 4 5 6 7 12 13 14 15 20 21 22 23

To check which logical CPUs are on the same core as CPU 1:

int my_cpu = 8;
int cpu_core = topo.domain_idx(GEOPM_DOMAIN_CORE, my_cpu);
std::set<int> core_cpu_set = topo.domain_nested(GEOPM_DOMAIN_CPU, GEOPM_DOMAIN_CORE, cpu_core);
for (auto cpu : core_cpu_set) {
    if (cpu != my_cpu) {
        std::cout << cpu << " ";
    }
}
std::cout << std::endl;

The output for the same system would be:

0 16

The number of domains can also be use to check if a hardware feature, such as on-package memory, is present or absent:

if (topo.num_domain(GEOPM_DOMAIN_PACKAGE_INTEGRATED_MEMORY) > 0) {
    std::cout << "On-package memory is present." << std::endl;
}
else {
    std::cout << "No on-package memory." << std::endl;
}

See Also

geopm(7), geopm_pio(3), geopm_topo(3), geopm::PlatformIO(3)