| author | wenzelm | 
| Wed, 27 May 2020 20:02:02 +0200 | |
| changeset 71910 | f8b0271cc744 | 
| parent 71601 | 97ccf48c2f0c | 
| child 75393 | 87ebf5a50283 | 
| permissions | -rw-r--r-- | 
| 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) {
 | 
| 71601 | 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 | |
| 68955 
0851db8cde12
more robust test: virtualization may provide misleading information;
 wenzelm parents: 
68954diff
changeset | 37 |   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 | 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 | 41 | |
| 68954 
8be4030394b8
implicit use of NUMA policy, absorbing potential errors;
 wenzelm parents: 
68953diff
changeset | 42 | def policy_options(options: Options, numa_node: Option[Int] = Some(0)): Options = | 
| 68953 | 43 |     numa_node match {
 | 
| 44 | case None => options | |
| 45 |       case Some(n) => options.string("ML_process_policy") = policy(n)
 | |
| 46 | } | |
| 47 | ||
| 64265 | 48 | |
| 49 | /* shuffling of CPU nodes */ | |
| 50 | ||
| 68954 
8be4030394b8
implicit use of NUMA policy, absorbing potential errors;
 wenzelm parents: 
68953diff
changeset | 51 | def enabled: Boolean = | 
| 
8be4030394b8
implicit use of NUMA policy, absorbing potential errors;
 wenzelm parents: 
68953diff
changeset | 52 |     try { nodes().length >= 2 && numactl_available }
 | 
| 
8be4030394b8
implicit use of NUMA policy, absorbing potential errors;
 wenzelm parents: 
68953diff
changeset | 53 |     catch { case ERROR(_) => false }
 | 
| 
8be4030394b8
implicit use of NUMA policy, absorbing potential errors;
 wenzelm parents: 
68953diff
changeset | 54 | |
| 65831 | 55 | def enabled_warning(progress: Progress, enabled: Boolean): Boolean = | 
| 64265 | 56 |   {
 | 
| 57 | def warning = | |
| 58 |       if (nodes().length < 2) Some("no NUMA nodes available")
 | |
| 68956 | 59 |       else if (!numactl_available) Some("bad numactl tool")
 | 
| 64265 | 60 | else None | 
| 61 | ||
| 62 | enabled && | |
| 63 |       (warning match {
 | |
| 65831 | 64 |         case Some(s) => progress.echo_warning("Shuffling of CPU nodes is disabled: " + s); false
 | 
| 64265 | 65 | case _ => true | 
| 66 | }) | |
| 67 | } | |
| 68 | ||
| 69 | class Nodes(enabled: Boolean = true) | |
| 70 |   {
 | |
| 71 | private val available = nodes().zipWithIndex | |
| 72 | private var next_index = 0 | |
| 73 | ||
| 74 |     def next(used: Int => Boolean = _ => false): Option[Int] = synchronized {
 | |
| 75 | if (!enabled || available.isEmpty) None | |
| 76 |       else {
 | |
| 77 | val candidates = available.drop(next_index) ::: available.take(next_index) | |
| 78 | val (n, i) = | |
| 79 |           candidates.find({ case (n, i) => i == next_index && !used(n) }) orElse
 | |
| 80 |             candidates.find({ case (n, _) => !used(n) }) getOrElse candidates.head
 | |
| 81 | next_index = (i + 1) % available.length | |
| 82 | Some(n) | |
| 83 | } | |
| 84 | } | |
| 85 | } | |
| 64264 
42138702d6ec
support for Non-Uniform Memory Access of separate CPU nodes;
 wenzelm parents: diff
changeset | 86 | } |