Skip to content

Commit

Permalink
refining how domain logic works
Browse files Browse the repository at this point in the history
  • Loading branch information
fearful-symmetry committed Nov 21, 2018
1 parent 4be159a commit 56bd1c6
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 74 deletions.
9 changes: 6 additions & 3 deletions gorapl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import (

func TestPowerLimit(t *testing.T) {

ret, err := ReadPowerLimit(DRAM)
h, err := NewRAPL(0)
if err != nil {
t.Fatalf("Could not init: %s", err)
}
dat, err := h.ReadPowerLimit(DRAM)
if err != nil {
t.Fatalf("Could not read MSR: %s", err)
}

fmt.Printf("Got back: %#v\n", ret)
fmt.Printf("Got back: %#v\n", dat)

}
72 changes: 36 additions & 36 deletions msrs.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package gorapl

import (
"fmt"
)

// //PkgPowerLimit is the MSR for package-level power limits
// //Fun fact: you can set this limit to 0, and the processor, will still work.
// const pkgPowerLimit = 0x610
Expand All @@ -30,50 +26,54 @@ type domainMSRs struct {

//This is a somewhat unorthidox syntax, but I'm not really a fan of cramming packages full of global `const` objects.
//For now we'll use 0x0 for MSRs that undefined for a given domain
var globalMSR = struct {
Pkg domainMSRs
DRAM domainMSRs
PP0 domainMSRs
PP1 domainMSRs
}{
domainMSRs{0x610, 0x611, 0x0, 0x613, 0x614},
domainMSRs{0x618, 0x619, 0x0, 0x61b, 0x61c},
domainMSRs{0x638, 0x639, 0x63a, 0x63a, 0x0},
domainMSRs{0x640, 0x641, 0x642, 0x0, 0x0},
}
// var globalMSR = struct {
// Pkg domainMSRs
// DRAM domainMSRs
// PP0 domainMSRs
// PP1 domainMSRs
// }{
// domainMSRs{0x610, 0x611, 0x0, 0x613, 0x614},
// domainMSRs{0x618, 0x619, 0x0, 0x61b, 0x61c},
// domainMSRs{0x638, 0x639, 0x63a, 0x63a, 0x0},
// domainMSRs{0x640, 0x641, 0x642, 0x0, 0x0},
// }

// The various RAPL domains

//RAPLDomain is a string type that covers the various RAPL domains
type RAPLDomain string
type RAPLDomain struct {
mask uint
name string
msrs domainMSRs
}

//Package is the RAPL domain for the CPU package
const Package RAPLDomain = "Package"
var Package = RAPLDomain{0x1, "Package", domainMSRs{0x610, 0x611, 0x0, 0x613, 0x614}}

//DRAM is the RAPL domain for the DRAM
const DRAM RAPLDomain = "DRAM"
var DRAM = RAPLDomain{0x2, "DRAM", domainMSRs{0x618, 0x619, 0x0, 0x61b, 0x61c}}

//PP0 is the RAPL domain for the processor core
const PP0 RAPLDomain = "PP0"
var PP0 = RAPLDomain{0x4, "PP0", domainMSRs{0x638, 0x639, 0x63a, 0x63a, 0x0}}

//PP1 is platform-dependant, although it usually referrs to some uncore power plane
const PP1 RAPLDomain = "PP1"

func getDomainMSRs(domain RAPLDomain) (domainMSRs, error) {

switch domain {
case Package:
return globalMSR.Pkg, nil
case DRAM:
return globalMSR.DRAM, nil
case PP0:
return globalMSR.PP0, nil
case PP1:
return globalMSR.PP1, nil
}

return domainMSRs{}, fmt.Errorf("No MSR for %s available", domain)
}
var PP1 = RAPLDomain{0x8, "PP1", domainMSRs{0x640, 0x641, 0x642, 0x0, 0x0}}

// func getDomainMSRs(domain RAPLDomain) (domainMSRs, error) {

// switch domain {
// case Package:
// return globalMSR.Pkg, nil
// case DRAM:
// return globalMSR.DRAM, nil
// case PP0:
// return globalMSR.PP0, nil
// case PP1:
// return globalMSR.PP1, nil
// }

// return domainMSRs{}, fmt.Errorf("No MSR for %s available", domain)
// }

// struct defs

Expand Down
40 changes: 30 additions & 10 deletions rapl.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@ package gorapl

import (
"fmt"

"github.com/fearful-symmetry/gomsr"
)

//RAPLHandler manages a stateful connection to the RAPL system.
type RAPLHandler struct {
availDomains []RAPLDomain //Available RAPL domains
domainMask uint //a bitmask to make it easier to find available domains
msrDev gomsr.MSRDev
}

//NewRAPL returns a new RAPL handler
func NewRAPL() (RAPLHandler, error) {
func NewRAPL(cpu int) (RAPLHandler, error) {

//TODO: eventually we'll need to handle multiple CPU packages
cpu := 0

domains := getAvailableDomains(cpu)
domains, mask := getAvailableDomains(cpu)
if len(domains) == 0 {
return RAPLHandler{}, fmt.Errorf("No RAPL domains available on CPU")
}
Expand All @@ -27,29 +28,48 @@ func NewRAPL() (RAPLHandler, error) {
return RAPLHandler{}, err
}

return RAPLHandler{availDomains: domains, msrDev: msr}, nil
return RAPLHandler{availDomains: domains, domainMask: mask, msrDev: msr}, nil
}

//ReadPowerLimit returns the MSR_[DOMAIN]_POWER_LIMIT MSR
func (h RAPLHandler) ReadPowerLimit(domain RAPLDomain) (RAPLPowerLimit, error) {

if (domain.mask & h.domainMask) == 0 {
return RAPLPowerLimit{}, fmt.Errorf("Domain %s does not exist on system", domain.name)
}

data, err := h.msrDev.Read(domain.msrs.PowerLimit)
if err != nil {
return RAPLPowerLimit{}, err
}
return parsePowerLimit(data), nil
}

//Borrowed this from the kernel. Traverse over the Energy Status MSRs to see what RAPL domains are available
func getAvailableDomains(cpu int) []RAPLDomain {
func getAvailableDomains(cpu int) ([]RAPLDomain, uint) {

var availDomains []RAPLDomain
var dm uint

if _, exists := gomsr.ReadMSR(cpu, globalMSR.Pkg.EnergyStatus); exists == nil {
if _, exists := gomsr.ReadMSR(cpu, Package.msrs.EnergyStatus); exists == nil {
availDomains = append(availDomains, Package)
dm = dm | Package.mask
}

if _, exists := gomsr.ReadMSR(cpu, globalMSR.DRAM.EnergyStatus); exists == nil {
if _, exists := gomsr.ReadMSR(cpu, DRAM.msrs.EnergyStatus); exists == nil {
availDomains = append(availDomains, DRAM)
dm = dm | DRAM.mask
}

if _, exists := gomsr.ReadMSR(cpu, globalMSR.PP0.Policy); exists == nil {
if _, exists := gomsr.ReadMSR(cpu, PP0.msrs.Policy); exists == nil {
availDomains = append(availDomains, PP0)
dm = dm | PP0.mask
}

if _, exists := gomsr.ReadMSR(cpu, globalMSR.PP1.EnergyStatus); exists == nil {
if _, exists := gomsr.ReadMSR(cpu, PP1.msrs.EnergyStatus); exists == nil {
availDomains = append(availDomains, PP1)
dm = dm | PP1.mask
}

return availDomains
return availDomains, dm
}
7 changes: 1 addition & 6 deletions rapl_oneshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ the package in question. Still, I'm not 100% sure.
//ReadPowerLimit Reads the MSR_[DOMAIN]_POWER_LIMIT MSR for the given domain
func ReadPowerLimit(domain RAPLDomain) (RAPLPowerLimit, error) {

msr, err := getDomainMSRs(domain)
if err != nil {
return RAPLPowerLimit{}, err
}

data, err := gomsr.ReadMSR(0, msr.PowerLimit)
data, err := gomsr.ReadMSR(0, domain.msrs.PowerLimit)
if err != nil {
return RAPLPowerLimit{}, err
}
Expand Down
47 changes: 28 additions & 19 deletions topo.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
package gorapl

import (
"fmt"
"io/ioutil"
"strings"
)

//this file represents my attemps at algos for uncovering the toplogy of the system we're running on, with respect to the physical CPU packages
//We have a problem: if we're running on a box with more than one physical CPU, we need to figure out what /dev/cpu/$cpu/msr device to access
//So we need to map logical CPUs to physical sockets
Expand All @@ -14,19 +8,34 @@ import (
//it is, however, the simplest way to do this. The intel power gaget iterates through each CPU using affinity masks, and runs `cpuid` in a loop to
//figure things out
//This uses /sys/devices/system/cpu/cpu*/topology/physical_package_id, which is what lscpu does. I *think* geopm does something similar to this.
func topoPkgCPUMap() ([]int, error) {
// func topoPkgCPUMap() ([]int, error) {

sysdir := "/sys/devices/system/cpu/"
var cpuMap map[int]int
files, err := ioutil.ReadDir(sysdir)
if err != nil {
return nil, err
}
// sysdir := "/sys/devices/system/cpu/"
// var cpuMap map[int]int
// re := regexp.MustCompile("cpu([0-9]*)")

for _, file := range files {
if file.IsDir() && strings.Contains(file.Name(), "cpu") {
fullPkg := fmt.Sprintf("%s%s/topology/physical_package_id")
// files, err := ioutil.ReadDir(sysdir)
// if err != nil {
// return nil, err
// }

}
}
}
// for _, file := range files {
// if file.IsDir() && strings.Contains(file.Name(), "cpu") {
// fullPkg := fmt.Sprintf("%s%s/topology/physical_package_id")
// match := re.FindStringSubmatch("git commit -m '${abc}'")
// thread, err := strconv.ParseInt(match[1], 10, 64)
// if err != nil {
// return nil, err
// }
// dat, err := ioutil.ReadFile(fullPkg)
// if err != nil {
// return nil, err
// }
// phys, err := strconv.ParseInt(string(dat), 10, 64)
// if err != nil {
// return nil, err
// }
// cpuMap[int(phys)] = int(thread)
// }
// }
// }

0 comments on commit 56bd1c6

Please sign in to comment.