cache line locking on AMD x86_64 utilising L3 CAT pseudo-locking
26

Configure Feed

Select the types of activity you want to include in your feed.

icepick / bindings / ocaml / icepick.ml
11 kB 314 lines
1open Ctypes 2open Foreign 3 4exception Icepick_error of string 5 6type prime_strategy = 7 | Prime_temporal 8 | Prime_prefetcht2 9 | Prime_prefetchnta 10 | Prime_nt_store 11 12type access_pattern = 13 | Pattern_sequential 14 | Pattern_reverse 15 | Pattern_strided 16 | Pattern_pointer_chase 17 18type core_type = 19 | Core_any 20 | Core_pcore 21 | Core_ecore 22 23let () = Callback.register_exception "Icepick_error" (Icepick_error "") 24 25let () = 26 let _ = Dl.dlopen ~filename:"/home/oni/Projects/icepick/libicepick.so" 27 ~flags:[Dl.RTLD_NOW; Dl.RTLD_GLOBAL] in 28 () 29 30module C = struct 31 let icepick_strerror = foreign "icepick_strerror" (int @-> returning string) 32 33 let check_error ret = 34 if ret < 0 then raise (Icepick_error (icepick_strerror ret)) 35 36 module Topology = struct 37 type t = unit ptr 38 let t : t typ = ptr void 39 40 let discover = foreign "icepick_discover_topology" (ptr t @-> returning int) 41 let free = foreign "icepick_free_topology" (t @-> returning void) 42 let l3_ways = foreign "icepick_topology_l3_ways" (t @-> returning uint) 43 let l3_size = foreign "icepick_topology_l3_size" (t @-> returning size_t) 44 let way_size = foreign "icepick_topology_way_size" (t @-> returning size_t) 45 let max_clos = foreign "icepick_topology_max_clos" (t @-> returning uint) 46 let ccx_count = foreign "icepick_topology_ccx_count" (t @-> returning uint) 47 let cat_supported = foreign "icepick_topology_cat_supported" (t @-> returning bool) 48 let mba_supported = foreign "icepick_topology_mba_supported" (t @-> returning bool) 49 let mba_is_linear = foreign "icepick_topology_mba_is_linear" (t @-> returning bool) 50 let max_mba_thrtl = foreign "icepick_topology_max_mba_thrtl" (t @-> returning uint) 51 let is_hybrid = foreign "icepick_topology_is_hybrid" (t @-> returning bool) 52 let pcore_count = foreign "icepick_topology_pcore_count" (t @-> returning uint) 53 let ecore_count = foreign "icepick_topology_ecore_count" (t @-> returning uint) 54 end 55 56 module Region = struct 57 type t = unit ptr 58 let t : t typ = ptr void 59 60 let ptr = foreign "icepick_region_ptr" (t @-> returning (ptr void)) 61 let size = foreign "icepick_region_size" (t @-> returning size_t) 62 let clos = foreign "icepick_region_clos" (t @-> returning uint) 63 end 64 65 module Config = struct 66 type t 67 let t : t structure typ = structure "icepick_config_t" 68 let size = field t "size" size_t 69 let clos_id = field t "clos_id" uint 70 let numa_node = field t "numa_node" int 71 let huge_pages = field t "huge_pages" bool 72 let verify = field t "verify" bool 73 let auto_monitor = field t "auto_monitor" bool 74 let pmu_poll_interval_ns = field t "pmu_poll_interval_ns" uint64_t 75 let probe_interval_ns = field t "probe_interval_ns" uint64_t 76 let miss_threshold = field t "miss_threshold" uint32_t 77 let prime_strategy = field t "prime_strategy" int 78 let access_pattern = field t "access_pattern" int 79 let stride_bytes = field t "stride_bytes" size_t 80 let prime_iterations = field t "prime_iterations" uint 81 let mba_throttle = field t "mba_throttle" uint 82 let core_type = field t "core_type" int 83 let () = seal t 84 end 85 86 module Latency_stats = struct 87 type t 88 let t : t structure typ = structure "icepick_latency_stats_t" 89 let mean_ns = field t "mean_ns" uint64_t 90 let stddev_ns = field t "stddev_ns" uint64_t 91 let p50_ns = field t "p50_ns" uint64_t 92 let p99_ns = field t "p99_ns" uint64_t 93 let p999_ns = field t "p999_ns" uint64_t 94 let min_ns = field t "min_ns" uint64_t 95 let max_ns = field t "max_ns" uint64_t 96 let () = seal t 97 end 98 99 let lock = foreign "icepick_lock" 100 (Topology.t @-> ptr Config.t @-> ptr Region.t @-> returning int) 101 102 let unlock = foreign "icepick_unlock" (Region.t @-> returning int) 103 104 let verify = foreign "icepick_verify" 105 (Region.t @-> ptr Latency_stats.t @-> returning int) 106 107 let bench = foreign "icepick_bench" 108 (ptr void @-> size_t @-> size_t @-> ptr Latency_stats.t @-> returning int) 109 110 module Monitor = struct 111 type t = unit ptr 112 let t : t typ = ptr void 113 114 let start = foreign "icepick_monitor_start" (Region.t @-> ptr t @-> returning int) 115 let start_ex = foreign "icepick_monitor_start_ex" 116 (Region.t @-> uint64_t @-> uint64_t @-> uint32_t @-> ptr t @-> returning int) 117 let stop = foreign "icepick_monitor_stop" (t @-> returning int) 118 let eviction_count = foreign "icepick_monitor_eviction_count" (t @-> returning uint64_t) 119 let reprime_count = foreign "icepick_monitor_reprime_count" (t @-> returning uint64_t) 120 let is_degraded = foreign "icepick_monitor_is_degraded" (t @-> returning bool) 121 end 122end 123 124module Topology = struct 125 type t = { 126 ptr : C.Topology.t; 127 mutable released : bool; 128 } 129 130 let release t = 131 if not t.released then begin 132 C.Topology.free t.ptr; 133 t.released <- true 134 end 135 136 let discover () = 137 let ptr_ref = allocate C.Topology.t (from_voidp void null) in 138 let ret = C.Topology.discover ptr_ref in 139 C.check_error ret; 140 let t = { ptr = !@ ptr_ref; released = false } in 141 Gc.finalise release t; 142 t 143 144 let l3_ways t = Unsigned.UInt.to_int (C.Topology.l3_ways t.ptr) 145 let l3_size t = Unsigned.Size_t.to_int (C.Topology.l3_size t.ptr) 146 let way_size t = Unsigned.Size_t.to_int (C.Topology.way_size t.ptr) 147 let max_clos t = Unsigned.UInt.to_int (C.Topology.max_clos t.ptr) 148 let ccx_count t = Unsigned.UInt.to_int (C.Topology.ccx_count t.ptr) 149 let cat_supported t = C.Topology.cat_supported t.ptr 150 let mba_supported t = C.Topology.mba_supported t.ptr 151 let mba_is_linear t = C.Topology.mba_is_linear t.ptr 152 let max_mba_thrtl t = Unsigned.UInt.to_int (C.Topology.max_mba_thrtl t.ptr) 153 let is_hybrid t = C.Topology.is_hybrid t.ptr 154 let pcore_count t = Unsigned.UInt.to_int (C.Topology.pcore_count t.ptr) 155 let ecore_count t = Unsigned.UInt.to_int (C.Topology.ecore_count t.ptr) 156end 157 158module Latency_stats = struct 159 type t = { 160 mean_ns : int; 161 stddev_ns : int; 162 p50_ns : int; 163 p99_ns : int; 164 p999_ns : int; 165 min_ns : int; 166 max_ns : int; 167 } 168 169 let of_c stats = 170 { 171 mean_ns = Unsigned.UInt64.to_int (getf stats C.Latency_stats.mean_ns); 172 stddev_ns = Unsigned.UInt64.to_int (getf stats C.Latency_stats.stddev_ns); 173 p50_ns = Unsigned.UInt64.to_int (getf stats C.Latency_stats.p50_ns); 174 p99_ns = Unsigned.UInt64.to_int (getf stats C.Latency_stats.p99_ns); 175 p999_ns = Unsigned.UInt64.to_int (getf stats C.Latency_stats.p999_ns); 176 min_ns = Unsigned.UInt64.to_int (getf stats C.Latency_stats.min_ns); 177 max_ns = Unsigned.UInt64.to_int (getf stats C.Latency_stats.max_ns); 178 } 179end 180 181module Region = struct 182 type t = { 183 ptr : C.Region.t; 184 topo : Topology.t; 185 mutable released : bool; 186 } 187 188 let release t = 189 if not t.released then begin 190 let _ = C.unlock t.ptr in 191 t.released <- true 192 end 193 194 let prime_strategy_to_int = function 195 | Prime_temporal -> 0 196 | Prime_prefetcht2 -> 1 197 | Prime_prefetchnta -> 2 198 | Prime_nt_store -> 3 199 200 let access_pattern_to_int = function 201 | Pattern_sequential -> 0 202 | Pattern_reverse -> 1 203 | Pattern_strided -> 2 204 | Pattern_pointer_chase -> 3 205 206 let core_type_to_int = function 207 | Core_any -> 0 208 | Core_pcore -> 1 209 | Core_ecore -> 2 210 211 let lock topo ~size ~clos ?(numa = -1) ?(huge_pages = true) ?(verify = false) 212 ?(prime_strategy = Prime_temporal) ?(access_pattern = Pattern_sequential) 213 ?(stride = 0) ?(prime_iterations = 3) ?(mba_throttle = 0) 214 ?(core_type = Core_any) () = 215 let cfg = make C.Config.t in 216 setf cfg C.Config.size (Unsigned.Size_t.of_int size); 217 setf cfg C.Config.clos_id (Unsigned.UInt.of_int clos); 218 setf cfg C.Config.numa_node numa; 219 setf cfg C.Config.huge_pages huge_pages; 220 setf cfg C.Config.verify verify; 221 setf cfg C.Config.auto_monitor false; 222 setf cfg C.Config.pmu_poll_interval_ns (Unsigned.UInt64.of_int 0); 223 setf cfg C.Config.probe_interval_ns (Unsigned.UInt64.of_int 0); 224 setf cfg C.Config.miss_threshold (Unsigned.UInt32.of_int 0); 225 setf cfg C.Config.prime_strategy (prime_strategy_to_int prime_strategy); 226 setf cfg C.Config.access_pattern (access_pattern_to_int access_pattern); 227 setf cfg C.Config.stride_bytes (Unsigned.Size_t.of_int stride); 228 setf cfg C.Config.prime_iterations (Unsigned.UInt.of_int prime_iterations); 229 setf cfg C.Config.mba_throttle (Unsigned.UInt.of_int mba_throttle); 230 setf cfg C.Config.core_type (core_type_to_int core_type); 231 let ptr_ref = allocate C.Region.t (from_voidp void null) in 232 let ret = C.lock topo.Topology.ptr (addr cfg) ptr_ref in 233 C.check_error ret; 234 let t = { ptr = !@ ptr_ref; topo; released = false } in 235 Gc.finalise release t; 236 t 237 238 let unlock t = 239 if not t.released then begin 240 let ret = C.unlock t.ptr in 241 t.released <- true; 242 C.check_error ret 243 end 244 245 let ptr t = raw_address_of_ptr (C.Region.ptr t.ptr) 246 let size t = Unsigned.Size_t.to_int (C.Region.size t.ptr) 247 let clos t = Unsigned.UInt.to_int (C.Region.clos t.ptr) 248 249 let to_bigarray_float64 t = 250 let region_ptr = C.Region.ptr t.ptr in 251 let region_size = Unsigned.Size_t.to_int (C.Region.size t.ptr) in 252 let len = region_size / 8 in 253 let typed_ptr = from_voidp double (to_voidp region_ptr) in 254 CArray.from_ptr typed_ptr len |> CArray.to_list |> Array.of_list |> 255 Bigarray.Array1.of_array Bigarray.Float64 Bigarray.c_layout 256end 257 258module Monitor = struct 259 type t = { 260 ptr : C.Monitor.t; 261 region : Region.t; 262 mutable stopped : bool; 263 } 264 265 let release t = 266 if not t.stopped then begin 267 let _ = C.Monitor.stop t.ptr in 268 t.stopped <- true 269 end 270 271 let start region = 272 let ptr_ref = allocate C.Monitor.t (from_voidp void null) in 273 let ret = C.Monitor.start region.Region.ptr ptr_ref in 274 C.check_error ret; 275 let t = { ptr = !@ ptr_ref; region; stopped = false } in 276 Gc.finalise release t; 277 t 278 279 let start_ex region ~pmu_poll_ns ~probe_ns ~miss_thresh = 280 let ptr_ref = allocate C.Monitor.t (from_voidp void null) in 281 let ret = C.Monitor.start_ex region.Region.ptr 282 (Unsigned.UInt64.of_int pmu_poll_ns) 283 (Unsigned.UInt64.of_int probe_ns) 284 (Unsigned.UInt32.of_int miss_thresh) 285 ptr_ref in 286 C.check_error ret; 287 let t = { ptr = !@ ptr_ref; region; stopped = false } in 288 Gc.finalise release t; 289 t 290 291 let stop t = 292 if not t.stopped then begin 293 let ret = C.Monitor.stop t.ptr in 294 t.stopped <- true; 295 C.check_error ret 296 end 297 298 let eviction_count t = Unsigned.UInt64.to_int (C.Monitor.eviction_count t.ptr) 299 let reprime_count t = Unsigned.UInt64.to_int (C.Monitor.reprime_count t.ptr) 300 let is_degraded t = C.Monitor.is_degraded t.ptr 301end 302 303let verify region = 304 let stats = make C.Latency_stats.t in 305 let ret = C.verify region.Region.ptr (addr stats) in 306 C.check_error ret; 307 Latency_stats.of_c stats 308 309let bench ptr ~size ~iterations = 310 let stats = make C.Latency_stats.t in 311 let p = ptr_of_raw_address ptr in 312 let ret = C.bench p (Unsigned.Size_t.of_int size) (Unsigned.Size_t.of_int iterations) (addr stats) in 313 C.check_error ret; 314 Latency_stats.of_c stats