Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Noric Couderc
JBrainy
Commits
beae7432
Commit
beae7432
authored
Nov 14, 2021
by
Noric Couderc
Browse files
Merge branch 'master' of git.cs.lth.se:noricc/jbrainy
parents
f54e0301
a2619d25
Changes
8
Hide whitespace changes
Inline
Side-by-side
core/src/main/kotlin/se/lth/cs/commandline/PapiCommandLine.kt
View file @
beae7432
...
...
@@ -12,6 +12,7 @@ import se.lth.cs.papicounters.MockupPapiTracerRunner
import
se.lth.cs.papicounters.PAPICounter
import
se.lth.cs.papicounters.PapiTracerRunner
import
se.lth.cs.util.brainyFeatures
import
se.lth.cs.util.normalize
import
java.io.File
import
java.io.FileReader
import
java.io.FileWriter
...
...
@@ -87,7 +88,7 @@ class PapiCommandLine : CliktCommand() {
PapiTracerRunner
()
}
val
features
=
brainyFeatures
()
val
features
=
if
(
normalizeFeatures
)
{
normalize
(
brainyFeatures
()).
checked
()
}
else
{
brainyFeatures
().
checked
()
}
SyntheticBenchmarkExperimentPrinter
(
writer
,
methodOutputFormat
,
numberRuns
,
features
,
...
...
core/src/main/kotlin/se/lth/cs/papicounters/EventSetBuilder.kt
View file @
beae7432
...
...
@@ -14,9 +14,12 @@ class EventSetBuilder : FeatureVisitor {
override
fun
visitPAPICounter
(
c
:
PAPICounter
)
{
// If the counter is de-activated we skip it
if
(
c
.
isActive
)
{
counterSet
.
add
(
c
)
if
(!
c
.
isSupported
())
{
val
msg
=
"Creating eventSet for single counter $c failed: is it available on this machine?"
throw
RuntimeException
(
msg
)
}
counterSet
.
add
(
c
)
}
override
fun
visitConstant
(
constantFeature
:
ConstantFeature
)
{
...
...
@@ -43,7 +46,7 @@ class EventSetBuilder : FeatureVisitor {
private
var
eventSet
:
EventSet
?
=
null
override
fun
visitFeatureSet
(
featureSet
:
FeatureSet
)
{
for
(
f
in
featureSet
.
features
)
{
for
(
f
in
featureSet
)
{
f
.
accept
(
this
)
}
...
...
core/src/main/kotlin/se/lth/cs/papicounters/PAPICounter.kt
View file @
beae7432
...
...
@@ -9,17 +9,11 @@ import se.lth.cs.util.FeatureVisitor
import
java.lang.RuntimeException
class
PAPICounter
(
val
counter
:
String
)
:
Feature
()
{
init
{
check
()
}
fun
isValid
():
Boolean
{
return
CounterSpecification
.
allCounters
.
contains
(
counter
)
}
var
isActive
:
Boolean
=
false
fun
check
()
{
override
fun
isSupported
():
Boolean
{
Papi
.
init
()
try
{
val
eventSet
=
EventSet
.
create
(
this
.
toPAPIConstant
()
!!
)
...
...
@@ -31,12 +25,9 @@ class PAPICounter(val counter : String) : Feature() {
// }
// eventSet.stop()
// eventSet.destroy()
isActive
=
true
return
true
}
catch
(
e
:
PapiException
)
{
val
msg
=
"Creating eventSet for single counter $counter failed: is it available on this machine? Deactivating..."
System
.
err
.
println
(
"[WARNING]: $msg"
)
isActive
=
false
return
false
}
}
...
...
core/src/main/kotlin/se/lth/cs/util/Experiment.kt
View file @
beae7432
...
...
@@ -12,9 +12,19 @@ class Experiment(val numberIterations : Int,
val
features
:
FeatureSet
,
val
papiRunner
:
PapiTracerRunner
)
:
FeatureVisitor
{
data class
Result
(
val
iterationNumber
:
Int
,
val
benchmark
:
BCBenchmarkPackage
<
*
>,
val
values
:
Map
<
Feature
,
Double
>)
inner
class
Result
(
val
iterationNumber
:
Int
,
val
benchmark
:
BCBenchmarkPackage
<
*
>,
val
values
:
Map
<
Feature
,
Double
>)
{
/**
* Returns only the features we specified in the feature set
* If feature F1 requires F2, but F2 is not explicitly requested
* we omit it.
*/
fun
strict
()
:
Result
{
return
Result
(
iterationNumber
,
benchmark
,
values
.
filterKeys
{
it
in
features
}
)
}
}
fun
getIterations
():
List
<
List
<
PapiTracerRunner
.
TraceRecord
>>
{
val
eventSetBuilder
=
EventSetBuilder
()
...
...
@@ -33,7 +43,7 @@ class Experiment(val numberIterations : Int,
}
fun
run
()
:
List
<
Result
>
{
if
(
features
.
features
.
isEmpty
())
{
return
listOf
()
}
if
(
features
.
isEmpty
())
{
return
listOf
()
}
val
iterations
=
getIterations
()
...
...
@@ -46,6 +56,7 @@ class Experiment(val numberIterations : Int,
// specific iteration!
features
.
accept
(
this
)
val
values
=
currentIterationResults
.
toMap
()
results
.
add
(
Result
(
iterationNumber
,
benchmark
,
values
))
iterationNumber
++
}
...
...
@@ -58,9 +69,6 @@ class Experiment(val numberIterations : Int,
var
currentIterationResults
:
MutableMap
<
Feature
,
Double
>
=
mutableMapOf
()
override
fun
visitPAPICounter
(
c
:
PAPICounter
)
{
if
(!
c
.
isActive
)
{
return
}
if
(
currentIterationResults
.
containsKey
(
c
))
{
return
}
...
...
@@ -105,7 +113,7 @@ class Experiment(val numberIterations : Int,
}
override
fun
visitFeatureSet
(
featureSet
:
FeatureSet
)
{
for
(
f
in
featureSet
.
features
)
{
for
(
f
in
featureSet
)
{
f
.
accept
(
this
)
}
}
...
...
core/src/main/kotlin/se/lth/cs/util/Features.kt
View file @
beae7432
...
...
@@ -42,6 +42,10 @@ abstract class Feature {
abstract
fun
featureType
()
:
Feature
.
Type
abstract
fun
accept
(
visitor
:
FeatureVisitor
)
open
fun
isSupported
()
:
Boolean
{
return
true
}
}
/**
...
...
@@ -96,7 +100,7 @@ class CostFeature(val opType : OperationType) : Feature() {
}
}
class
FeatureRatio
(
val
f1
:
Feature
,
val
f2
:
Feature
)
:
Feature
()
{
open
class
FeatureRatio
(
val
f1
:
Feature
,
val
f2
:
Feature
)
:
Feature
()
{
override
fun
featureType
():
Type
{
return
Type
.
RATIO
}
...
...
@@ -108,6 +112,10 @@ class FeatureRatio(val f1 : Feature, val f2 : Feature) : Feature() {
override
fun
toString
():
String
{
return
"%s / %s"
.
format
(
f1
.
toString
(),
f2
.
toString
())
}
override
fun
isSupported
():
Boolean
{
return
f1
.
isSupported
()
&&
f2
.
isSupported
()
}
}
class
MethodInvocations
(
val
method
:
String
,
val
methodPrintFormat
:
String
)
:
Feature
()
{
...
...
@@ -151,25 +159,32 @@ class TotalMethodInvocations() : Feature() {
}
/**
*
This is how we normalize some features,
* by
taking the ratio with some others:
*
example: Normalize PAPI_L1_DCM by PAPI_TOT_CYC
*
is just dividing
*
Normalized features are features, except you divide them
* by
a normalization features.
*
*
They are, not printed the same way as feature ratios, though.
*/
fun
normalize
(
f
:
Feature
,
n
:
Feature
):
Feature
{
return
FeatureRatio
(
f
,
n
)
class
NormalizedFeature
(
f
:
Feature
,
n
:
Feature
)
:
FeatureRatio
(
f
,
n
)
{
override
fun
featureType
():
Type
{
return
f1
.
featureType
()
}
override
fun
toString
():
String
{
return
"$f1 (normalized by $f2)"
}
}
fun
defaultNormalize
(
f
:
Feature
)
:
Feature
?
{
fun
defaultNormalize
(
f
:
Feature
)
:
Feature
{
if
(
f
.
featureType
()
==
Feature
.
Type
.
SOFTWARE
)
{
return
n
ormalize
(
f
,
TotalMethodInvocations
())
return
N
ormalize
dFeature
(
f
,
TotalMethodInvocations
())
}
if
(
f
.
featureType
()
==
Feature
.
Type
.
HARDWARE
)
{
return
n
ormalize
(
f
,
PAPICounter
(
"PAPI_TOT_CYC"
))
return
N
ormalize
dFeature
(
f
,
PAPICounter
(
"PAPI_TOT_CYC"
))
}
return
null
// When we don't know, we just return the feature as-is.
return
f
}
/**
...
...
@@ -178,26 +193,72 @@ fun defaultNormalize(f : Feature) : Feature? {
* (For example: Create ONE papi event set for the
* whole of the features)
*/
class
FeatureSet
(
val
features
:
List
<
Feature
>)
{
class
FeatureSet
(
vararg
features
:
Feature
)
:
ArrayList
<
Feature
>()
{
init
{
for
(
f
in
features
)
{
this
.
add
(
f
)
}
}
/**
* Returns a subset of features which should be supported by the current machine!
*/
fun
checked
()
:
FeatureSet
{
val
featuresChecked
=
this
.
partition
{
it
.
isSupported
()
}
System
.
err
.
println
(
"[WARNING]: Some features have been dropped, they are not supported on this machine: ${featuresChecked.second}"
)
return
FeatureSet
(*
featuresChecked
.
first
.
toTypedArray
())
}
fun
accept
(
visitor
:
FeatureVisitor
)
{
visitor
.
visitFeatureSet
(
this
)
}
}
/**
* We normalize a featureSet by applying normalization on all the features!
*/
// TODO: This could be a method
fun
normalize
(
featureSet
:
FeatureSet
):
FeatureSet
{
val
features
=
featureSet
.
map
{
defaultNormalize
(
it
)
}.
toTypedArray
()
return
FeatureSet
(*
features
)
}
fun
cacheLineSizeFeature
():
HardwareConstantFeature
?
{
val
processBuilder
=
ProcessBuilder
()
processBuilder
.
command
(
"getconf"
,
"LEVEL1_DCACHE_LINESIZE"
)
val
process
=
processBuilder
.
start
()
val
input
=
process
.
inputStream
val
lines
=
input
.
bufferedReader
().
lines
()
// "orElse(null)" :C
val
cacheSize
:
HardwareConstantFeature
?
=
lines
.
findFirst
().
map
{
Integer
.
parseInt
(
it
)
}
.
map
{
HardwareConstantFeature
(
"Cache Block Size"
,
it
.
toDouble
())
}.
orElse
(
null
)
return
cacheSize
}
fun
brainyFeatures
()
:
FeatureSet
{
// We need to get the cache block size on this machine
val
dataSizeFeature
=
SoftwareConstantFeature
(
"Data Size"
,
Integer
.
BYTES
.
toDouble
())
val
cacheSize
=
cacheLineSizeFeature
()
val
sizesRatioFeature
=
if
(
cacheSize
==
null
)
{
dataSizeFeature
}
else
{
FeatureRatio
(
dataSizeFeature
,
cacheSize
)
}
return
FeatureSet
(
se
.
lth
.
cs
.
listOf
(
PAPICounter
(
"PAPI_BR_MSP"
),
PAPICounter
(
"PAPI_BR_MSP"
),
PAPICounter
(
"PAPI_L1_DCM"
),
FeatureRatio
(
PAPICounter
(
"PAPI_L1_DCM"
),
PAPICounter
(
"PAPI_L1_DCA"
)
),
FeatureRatio
(
SoftwareConstantFeature
(
"Data Size"
,
Integer
.
BYTES
.
toDouble
()),
// Type "getconf -a | grep "CACHE" to find this.
// TODO: Make this automatic
HardwareConstantFeature
(
"Cache Block Size"
,
64.0
)
),
sizesRatioFeature
,
FeatureRatio
(
PAPICounter
(
"PAPI_BR_MSP"
),
PAPICounter
(
"PAPI_BR_CN"
)
...
...
@@ -205,5 +266,5 @@ fun brainyFeatures() : FeatureSet {
CostFeature
(
OperationType
.
SEARCH
),
CostFeature
(
OperationType
.
ITERATE
),
CostFeature
(
OperationType
.
INSERT
),
CostFeature
(
OperationType
.
DELETE
))
)
CostFeature
(
OperationType
.
DELETE
))
}
core/src/test/kotlin/EventSetBuilderTest.kt
View file @
beae7432
...
...
@@ -35,7 +35,7 @@ class EventSetBuilderTest {
PAPICounter
(
"PAPI_L1_DCM"
)
)
val
spec
=
FeatureSet
(
counters
)
val
spec
=
FeatureSet
(
*
counters
.
toTypedArray
()
)
val
builder
=
EventSetBuilder
()
spec
.
accept
(
builder
)
...
...
@@ -48,9 +48,9 @@ class EventSetBuilderTest {
val
features
=
listOf
(
CostFeature
(
OperationType
.
INSERT
),
PAPICounter
(
"PAPI_L1_DCM"
)
)
)
.
toTypedArray
()
val
spec
=
FeatureSet
(
features
)
val
spec
=
FeatureSet
(
*
features
)
val
builder
=
EventSetBuilder
()
spec
.
accept
(
builder
)
...
...
@@ -76,9 +76,9 @@ class EventSetBuilderTest {
CostFeature
(
OperationType
.
INSERT
),
CostFeature
(
OperationType
.
DELETE
)
)
)
)
.
toTypedArray
()
val
spec
=
FeatureSet
(
features
)
val
spec
=
FeatureSet
(
*
features
)
val
builder
=
EventSetBuilder
()
spec
.
accept
(
builder
)
...
...
@@ -97,13 +97,12 @@ class EventSetBuilderTest {
fun
testEventBuildInvalidEvents
()
{
val
features
=
listOf
(
PAPICounter
(
"PAPI_L1_DCM"
),
PAPICounter
(
"PAPI_L1_DCA"
))
PAPICounter
(
"PAPI_L1_DCA"
))
.
toTypedArray
()
val
spec
=
FeatureSet
(
features
)
val
spec
=
FeatureSet
(
*
features
)
// Oh no! empty list of PAPI events!
val
builder
=
EventSetBuilder
()
spec
.
accept
(
builder
)
// Assertions.assertThrows(RuntimeException::class.java, { spec.accept(builder) })
Assertions
.
assertThrows
(
RuntimeException
::
class
.
java
)
{
spec
.
accept
(
builder
)
}
}
}
\ No newline at end of file
core/src/test/kotlin/ExperimentTest.kt
View file @
beae7432
...
...
@@ -16,7 +16,7 @@ class ExperimentTest {
fun
testExperimentNoFeatures
()
{
val
bench
=
BCBenchmarkPackage
.
LIST
(
1234
,
100
,
0
,
ArrayList
<
Int
>())
val
exp
=
Experiment
(
10
,
bench
,
FeatureSet
(
listOf
()
),
runner
)
val
exp
=
Experiment
(
10
,
bench
,
FeatureSet
(),
runner
)
val
results
=
exp
.
run
()
Assertions
.
assertTrue
(
results
.
isEmpty
())
...
...
@@ -26,9 +26,7 @@ class ExperimentTest {
fun
testExperiment1
()
{
val
bench
=
BCBenchmarkPackage
.
LIST
(
1234
,
100
,
0
,
ArrayList
<
Int
>())
val
exp
=
Experiment
(
10
,
bench
,
FeatureSet
(
listOf
(
PAPICounter
(
"PAPI_TOT_CYC"
))
),
FeatureSet
(
PAPICounter
(
"PAPI_TOT_CYC"
)),
runner
)
...
...
@@ -59,11 +57,9 @@ class ExperimentTest {
val
exp
=
Experiment
(
10
,
bench
,
FeatureSet
(
listOf
(
PAPICounter
(
"PAPI_TOT_INS"
),
costPerDelete
,
cacheMissRate
)
PAPICounter
(
"PAPI_TOT_INS"
),
costPerDelete
,
cacheMissRate
),
runner
)
...
...
@@ -84,15 +80,38 @@ class ExperimentTest {
fun
testExperimentBrainyFeatures
()
{
val
bench
=
BCBenchmarkPackage
.
LIST
(
1234
,
100
,
0
,
ArrayList
<
Int
>())
val
features
=
brainyFeatures
()
val
features
=
brainyFeatures
()
.
checked
()
val
exp
=
Experiment
(
10
,
bench
,
features
,
runner
)
val
results
=
exp
.
run
()
for
(
iteration
in
results
)
{
Assertions
.
assertEquals
(
bench
,
iteration
.
benchmark
)
Assertions
.
assertTrue
(
iteration
.
values
.
values
.
all
{
it
>
0
})
}
}
@Test
fun
cacheSizeFeatures
()
{
val
f
=
cacheLineSizeFeature
()
Assertions
.
assertFalse
(
f
==
null
)
}
@Test
fun
testNormalizationBrainyFeatures
()
{
val
bench
=
BCBenchmarkPackage
.
LIST
(
1234
,
100
,
0
,
ArrayList
<
Int
>())
val
features
=
normalize
(
brainyFeatures
()).
checked
()
val
exp
=
Experiment
(
10
,
bench
,
features
,
runner
)
val
results
=
exp
.
run
()
for
(
iteration
in
results
)
{
Assertions
.
assertEquals
(
bench
,
iteration
.
benchmark
)
Assertions
.
assertTrue
(
features
.
containsAll
(
iteration
.
strict
().
values
.
keys
))
Assertions
.
assertTrue
(
iteration
.
values
.
values
.
all
{
it
>
0
})
Assertions
.
assertTrue
(
iteration
.
strict
().
values
.
values
.
all
{
it
<=
1.0
})
}
}
}
\ No newline at end of file
core/src/test/kotlin/SyntheticBenchmarkExperimentPrinterTest.kt
View file @
beae7432
...
...
@@ -20,10 +20,8 @@ class SyntheticBenchmarkExperimentPrinterTest {
fun
testNoBenchmarks
()
{
val
writer
=
StringWriter
()
val
features
=
FeatureSet
(
listOf
(
PAPICounter
(
"PAPI_TOT_CYC"
),
MethodInvocations
(
"java.util.List.add"
,
"JAVA-STANDARD-FORMAT"
)
)
PAPICounter
(
"PAPI_TOT_CYC"
),
MethodInvocations
(
"java.util.List.add"
,
"JAVA-STANDARD-FORMAT"
)
)
val
printer
=
SyntheticBenchmarkExperimentPrinter
(
writer
,
""
,
...
...
@@ -41,11 +39,9 @@ class SyntheticBenchmarkExperimentPrinterTest {
fun
testListBenchmarks
()
{
val
writer
=
StringWriter
()
val
features
=
FeatureSet
(
listOf
(
PAPICounter
(
"PAPI_TOT_CYC"
),
CostFeature
(
OperationType
.
INSERT
),
MethodInvocations
(
"runAdd"
,
"JAVA-STANDARD-FORMAT"
)
)
PAPICounter
(
"PAPI_TOT_CYC"
),
CostFeature
(
OperationType
.
INSERT
),
MethodInvocations
(
"runAdd"
,
"JAVA-STANDARD-FORMAT"
)
)
val
printer
=
SyntheticBenchmarkExperimentPrinter
(
writer
,
""
,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment