src/Pure/System/numa.scala
author wenzelm
Fri, 27 Oct 2017 11:46:03 +0200
changeset 66923 914935f8a462
parent 65831 3b197547c1d4
child 68953 89a12af9c330
permissions -rw-r--r--
tuned;
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
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    10
object NUMA
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    11
{
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    12
  /* available nodes */
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    13
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    14
  def nodes(): List[Int] =
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 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
    17
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    18
    val Single = """^(\d+)$""".r
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    19
    val Multiple = """^(\d+)-(\d+)$""".r
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    20
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    21
    def read(s: String): List[Int] =
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    22
      s match {
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    23
        case Single(Value.Int(i)) => List(i)
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    24
        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
    25
        case _ => error("Cannot parse CPU node specification: " + quote(s))
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    26
      }
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    27
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    28
    if (numa_nodes_linux.is_file) {
66923
wenzelm
parents: 65831
diff changeset
    29
      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
    30
    }
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    31
    else Nil
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
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    34
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    35
  /* CPU policy via numactl tool */
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
  lazy val numactl_available: Boolean = Isabelle_System.bash("numactl --hardware").ok
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    38
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    39
  def policy(node: Int): String =
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    40
    if (numactl_available) "numactl -m" + node + " -N" + node else ""
64265
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    41
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    42
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    43
  /* shuffling of CPU nodes */
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    44
65831
3b197547c1d4 prefer explicit progress channel;
wenzelm
parents: 64497
diff changeset
    45
  def enabled_warning(progress: Progress, enabled: Boolean): Boolean =
64265
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    46
  {
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    47
    def warning =
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    48
      if (nodes().length < 2) Some("no NUMA nodes available")
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    49
      else if (!numactl_available) Some("missing numactl tool")
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    50
      else None
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    51
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    52
    enabled &&
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    53
      (warning match {
65831
3b197547c1d4 prefer explicit progress channel;
wenzelm
parents: 64497
diff changeset
    54
        case Some(s) => progress.echo_warning("Shuffling of CPU nodes is disabled: " + s); false
64265
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    55
        case _ => true
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    56
      })
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    57
  }
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    58
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    59
  class Nodes(enabled: Boolean = true)
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    60
  {
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    61
    private val available = nodes().zipWithIndex
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    62
    private var next_index = 0
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    63
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    64
    def next(used: Int => Boolean = _ => false): Option[Int] = synchronized {
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    65
      if (!enabled || available.isEmpty) None
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    66
      else {
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    67
        val candidates = available.drop(next_index) ::: available.take(next_index)
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    68
        val (n, i) =
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    69
          candidates.find({ case (n, i) => i == next_index && !used(n) }) orElse
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    70
            candidates.find({ case (n, _) => !used(n) }) getOrElse candidates.head
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    71
        next_index = (i + 1) % available.length
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    72
        Some(n)
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    73
      }
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    74
    }
8eb6365f5916 isabelle build -N;
wenzelm
parents: 64264
diff changeset
    75
  }
64264
42138702d6ec support for Non-Uniform Memory Access of separate CPU nodes;
wenzelm
parents:
diff changeset
    76
}