src/Pure/System/numa.scala
author wenzelm
Fri, 01 Apr 2022 17:06:10 +0200
changeset 75393 87ebf5a50283
parent 71601 97ccf48c2f0c
child 77316 d17b0851a61a
permissions -rw-r--r--
clarified formatting, for the sake of scala3;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
64264
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/System/numa.scala
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
     3
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
     4
Support for Non-Uniform Memory Access of separate CPU nodes.
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
     5
*/
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
     6
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
     7
package isabelle
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
     8
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
     9
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 71601
diff changeset
    10
object NUMA {
64264
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    11
  /* available nodes */
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    12
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 71601
diff changeset
    13
  def nodes(): List[Int] = {
64264
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    14
    val numa_nodes_linux = Path.explode("/sys/devices/system/node/online")
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    15
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    16
    val Single = """^(\d+)$""".r
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    17
    val Multiple = """^(\d+)-(\d+)$""".r
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    18
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    19
    def read(s: String): List[Int] =
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    20
      s match {
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    21
        case Single(Value.Int(i)) => List(i)
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    22
        case Multiple(Value.Int(i), Value.Int(j)) => (i to j).toList
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    23
        case _ => error("Cannot parse CPU node specification: " + quote(s))
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    24
      }
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    25
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    26
    if (numa_nodes_linux.is_file) {
71601
97ccf48c2f0c misc tuning based on hints by IntelliJ IDEA;
wenzelm
parents: 68956
diff changeset
    27
      space_explode(',', File.read(numa_nodes_linux).trim).flatMap(read)
64264
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    28
    }
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    29
    else Nil
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    30
  }
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    31
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    32
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    33
  /* CPU policy via numactl tool */
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    34
68955
0851db8cde12 more robust test: virtualization may provide misleading information;
wenzelm
parents: 68954
diff changeset
    35
  lazy val numactl_available: Boolean = Isabelle_System.bash("numactl -m0 -N0 true").ok
64264
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    36
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    37
  def policy(node: Int): String =
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    38
    if (numactl_available) "numactl -m" + node + " -N" + node else ""
64265
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    39
68954
8be4030394b8 implicit use of NUMA policy, absorbing potential errors;
wenzelm
parents: 68953
diff changeset
    40
  def policy_options(options: Options, numa_node: Option[Int] = Some(0)): Options =
68953
89a12af9c330 tuned signature;
wenzelm
parents: 66923
diff changeset
    41
    numa_node match {
89a12af9c330 tuned signature;
wenzelm
parents: 66923
diff changeset
    42
      case None => options
89a12af9c330 tuned signature;
wenzelm
parents: 66923
diff changeset
    43
      case Some(n) => options.string("ML_process_policy") = policy(n)
89a12af9c330 tuned signature;
wenzelm
parents: 66923
diff changeset
    44
    }
89a12af9c330 tuned signature;
wenzelm
parents: 66923
diff changeset
    45
64265
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    46
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    47
  /* shuffling of CPU nodes */
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    48
68954
8be4030394b8 implicit use of NUMA policy, absorbing potential errors;
wenzelm
parents: 68953
diff changeset
    49
  def enabled: Boolean =
8be4030394b8 implicit use of NUMA policy, absorbing potential errors;
wenzelm
parents: 68953
diff changeset
    50
    try { nodes().length >= 2 && numactl_available }
8be4030394b8 implicit use of NUMA policy, absorbing potential errors;
wenzelm
parents: 68953
diff changeset
    51
    catch { case ERROR(_) => false }
8be4030394b8 implicit use of NUMA policy, absorbing potential errors;
wenzelm
parents: 68953
diff changeset
    52
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 71601
diff changeset
    53
  def enabled_warning(progress: Progress, enabled: Boolean): Boolean = {
64265
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    54
    def warning =
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    55
      if (nodes().length < 2) Some("no NUMA nodes available")
68956
122c0d6cb790 tuned message;
wenzelm
parents: 68955
diff changeset
    56
      else if (!numactl_available) Some("bad numactl tool")
64265
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    57
      else None
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    58
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    59
    enabled &&
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    60
      (warning match {
65831
3b197547c1d4 prefer explicit progress channel;
wenzelm
parents: 64497
diff changeset
    61
        case Some(s) => progress.echo_warning("Shuffling of CPU nodes is disabled: " + s); false
64265
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    62
        case _ => true
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    63
      })
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    64
  }
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    65
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 71601
diff changeset
    66
  class Nodes(enabled: Boolean = true) {
64265
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    67
    private val available = nodes().zipWithIndex
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    68
    private var next_index = 0
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    69
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    70
    def next(used: Int => Boolean = _ => false): Option[Int] = synchronized {
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    71
      if (!enabled || available.isEmpty) None
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    72
      else {
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    73
        val candidates = available.drop(next_index) ::: available.take(next_index)
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    74
        val (n, i) =
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    75
          candidates.find({ case (n, i) => i == next_index && !used(n) }) orElse
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    76
            candidates.find({ case (n, _) => !used(n) }) getOrElse candidates.head
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    77
        next_index = (i + 1) % available.length
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    78
        Some(n)
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    79
      }
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    80
    }
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    81
  }
64264
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    82
}