Experiment.kt 4.32 KB
Newer Older
1
2
package se.lth.cs.util

Noric Couderc's avatar
Noric Couderc committed
3
4
5
6
7
8
import se.lth.cs.bcgen.BCBenchmarkPackage
import se.lth.cs.papicounters.EventSetBuilder
import se.lth.cs.papicounters.PAPICounter
import se.lth.cs.papicounters.PapiBenchmarkAnalyzer
import se.lth.cs.papicounters.PapiTracerRunner
import se.lth.cs.timing.OperationTypeTable
9
import java.util.stream.Stream
Noric Couderc's avatar
Noric Couderc committed
10
11
12

class Experiment(val numberIterations : Int,
                 val benchmark : BCBenchmarkPackage<*>,
13
14
                 val features : FeatureSet,
                 val papiRunner : PapiTracerRunner) : FeatureVisitor {
Noric Couderc's avatar
Noric Couderc committed
15

16
17
18
19
20
21
22
23
24
25
26
27
28
    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 } )
        }
    }
Noric Couderc's avatar
Noric Couderc committed
29

30
    fun getIterations(): Stream<List<PapiTracerRunner.TraceRecord>> {
31
        val eventSetBuilder = EventSetBuilder()
Noric Couderc's avatar
Noric Couderc committed
32
        eventSetBuilder.visitFeatureSet(features)
33

34
        val counters = eventSetBuilder.getCounterSet()
Noric Couderc's avatar
Noric Couderc committed
35
36
37
        val evSet = eventSetBuilder.getEventSet()

        val iterations = papiRunner.runIterations(
38
            PapiBenchmarkAnalyzer.RunSpec(numberIterations, counters.toList(), evSet, benchmark)
Noric Couderc's avatar
Noric Couderc committed
39
40
        )

41
        return iterations.stream()
42
43
    }

44
45
46
47
48
49
50
51
52
53
54
55
56
57
    private fun runIteration(i : List<PapiTracerRunner.TraceRecord>,
                     iterationNumber: Int): Result {
        currentIteration = i
        currentIterationResults = mutableMapOf()
        // We aggregate all our features for that
        // specific iteration!
        features.accept(this)
        val values = currentIterationResults.toMap()

        return Result(iterationNumber, benchmark, values)
    }

    fun run() : Stream<Result> {
        if (features.isEmpty()) { return Stream.empty() }
58
59
60

        val iterations = getIterations()

Noric Couderc's avatar
Noric Couderc committed
61
        var iterationNumber = 0
62

63
64
        return iterations.map {
            val r = runIteration(it, iterationNumber)
Noric Couderc's avatar
Noric Couderc committed
65
            iterationNumber++
66
            r
Noric Couderc's avatar
Noric Couderc committed
67
68
69
70
71
72
73
74
        }
    }

    var currentIteration : List<PapiTracerRunner.TraceRecord> = listOf()

    var currentIterationResults : MutableMap<Feature, Double> = mutableMapOf()

    override fun visitPAPICounter(c: PAPICounter) {
Noric Couderc's avatar
Noric Couderc committed
75
        if (currentIterationResults.containsKey(c)) {
76
            return
Noric Couderc's avatar
Noric Couderc committed
77
78
        }

Noric Couderc's avatar
Noric Couderc committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
        val values = currentIteration.filter { it.featureName == c.toHexa() }
            .map { it.featureValue }

        currentIterationResults[c] = values.sum().toDouble()
    }

    override fun visitConstant(constantFeature: ConstantFeature) {
        currentIterationResults[constantFeature] = constantFeature.value
    }

    override fun visitCost(costFeature: CostFeature) {
        costFeature.counter.accept(this)

        val sum = currentIteration.filter {
            val methodType = OperationTypeTable.getType(it.method)

            val rightMethodType = methodType.map { opType ->
                opType == costFeature.opType
            }.orElse(false)

            val rightCounter = it.featureName == costFeature.counter.toHexa()
            rightMethodType && rightCounter
        }.sumBy { it.featureValue }

        currentIterationResults[costFeature] = sum.toDouble()
    }

    override fun visitRatio(featureRatio: FeatureRatio) {
        featureRatio.f1.accept(this)
        featureRatio.f2.accept(this)

110
111
        val f1Value = currentIterationResults[featureRatio.f1]
        val f2Value = currentIterationResults[featureRatio.f2]
Noric Couderc's avatar
Noric Couderc committed
112

113
114
115
        if (f1Value != null && f2Value != null) {
            currentIterationResults[featureRatio] = f1Value / f2Value
        }
Noric Couderc's avatar
Noric Couderc committed
116
117
118
    }

    override fun visitFeatureSet(featureSet: FeatureSet) {
119
        for (f in featureSet) {
Noric Couderc's avatar
Noric Couderc committed
120
121
122
123
124
125
126
127
128
129
130
131
            f.accept(this)
        }
    }

    override fun visitMethodInvocations(methodInvocations: MethodInvocations) {
        val invokes = benchmark.methodHistogram()[methodInvocations.method]!!
        currentIterationResults[methodInvocations] = invokes.toDouble()
    }

    override fun visitTotalMethodInvocations(totalMethodInvocations: TotalMethodInvocations) {
        currentIterationResults[totalMethodInvocations] = benchmark.traceSize.toDouble()
    }
132
}