Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions papier/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.o
*.a
*.so
.ptp-sync*
.cproject
.project
.settings
forge/
74 changes: 74 additions & 0 deletions papier/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#############################################################################
#
# Papier top-level makefile.
#
# Copyright (c) Arm Inc.
#
# Created August 2019
# John Linford <john.linford@arm.com>
#
#############################################################################


# Update as needed:
# Path to the MAP metrics directory, e.g. forge/map/metrics.
# The metric plugin API header files should be in 'include/'
ifeq ($(MAP_METRICS_DIR),)
MAP_METRICS_DIR := /opt/arm/forge/19.0.2/map/metrics
endif

# Update as needed:
# Directory where custom metrics should be installed, i.e.
# the Allinea Forge configuration directory
ifeq ($(FORGE_CONFIG_DIR),)
FORGE_CONFIG_DIR := ~/.allinea
endif

# Update as needed:
# Directory where PAPI is installed
ifeq ($(PAPI_DIR),)
PAPI_DIR = /opt/arm/papi/papi-5.6.1.0-custom
endif

# Update as needed:
# Toolchain configuration
CXX = g++
CXXFLAGS = -Wall -std=c++11 -fPIC -I$(MAP_METRICS_DIR)/include -I$(PAPI_DIR)/include
LD = $(CXX)
LDFLAGS = -L$(PAPI_DIR)/lib
LIBS = -lpapi -lm

#############################################################################

INSTALLDIR = $(FORGE_CONFIG_DIR)/map/metrics

LIBPAPIER_LIB = libpapier.so
LIBPAPIER_SRC = $(wildcard *.cpp)
LIBPAPIER_HDR = $(wildcard *.hpp)
LIBPAPIER_OBJ = $(LIBPAPIER_SRC:.cpp=.o)

PAPIER_XML = papier.xml

TARGETS = $(LIBPAPIER_LIB) $(PAPIER_XML)
OBJ = $(LIBPAPIER_OBJ)


.PHONY: all install clean

all: $(TARGETS)

install: $(TARGETS) $(INSTALLDIR)
cp $(TARGETS) $(INSTALLDIR)

clean:
rm -f $(OBJ) $(TARGETS)

$(LIBPAPIER_LIB): $(LIBPAPIER_OBJ)
$(LD) $(LDFLAGS) -shared -o $@ $^ $(LIBS)

%.o: %.cpp $(LIBPAPIER_HDR)
$(CXX) -c $(CXXFLAGS) -o $@ $<

$(FORGE_CONFIG_DIR)/%:
mkdir -p $@

149 changes: 149 additions & 0 deletions papier/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
Papier: Performance Measurement from Mathematical Expressions
=============================================================

Papier is an extensible performance measurement system provided
as a custom metric for Arm MAP. It enables MAP to calculate
arbitrary mathematical expressions involving data gathered from
multiple measurement systems, e.g. perf, PAPI, CUPTI, or the OS.

Quick Start
-----------

* Edit Makefile as needed and `make install`
* `export ALLINEA_PAPIER_EXPRESSION="(PAPI{PAPI_FP_INS} + PAPI{PAPI_VEC_INS}) / PAPI{PAPI_TOT_INS}"`
* `map [options] ./a.out`

Usage
-----

Set the `ALLINEA_PAPIER_EXPRESSION` environment variable to
the expression itself or a path to a file containing the
expression. Once the custom metric is installed you won't have
to recompile or write code or anything to get new data. Just
set an environment variable and you're done!

The syntax for specifying metrics is `<SYSTEM>{METRIC}`, e.g.
PAPI{PAPI_L1_TCM} or TIME{WALLCLOCK} or PAPI{perf_raw::r0156}.
See "Measurement Systems" below for more details.

The front end is based on [ExprTk][1], so performance metrics
can be defined with \rich mathematical expressions e.g. these
are all valid expressions (copied from the ExprTk readme):

- `sqrt(1 - (3 / x^2))`
- `clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1)`
- `sin(2.34e-3 * x)`
- `if(((x[2] + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z)`
- `inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0)`
- `({1/1}*[1/2]+(1/3))-{1/4}^[1/5]+(1/6)-({1/7}+[1/8]*(1/9))`
- `a * exp(2.2 / 3.3 * t) + c`
- `z := x + sin(2.567 * pi / y)`
- `u := 2.123 * {pi * z} / (w := x + cos(y / pi))`
- `2x + 3y + 4z + 5w == 2 * x + 3 * y + 4 * z + 5 * w`
- `3(x + y) / 2.9 + 1.234e+12 == 3 * (x + y) / 2.9 + 1.234e+12`
- `(x + y)3.3 + 1 / 4.5 == [x + y] * 3.3 + 1 / 4.5`
- `(x + y[i])z + 1.1 / 2.7 == (x + y[i]) * z + 1.1 / 2.7`
- `(sin(x / pi) cos(2y) + 1) == (sin(x / pi) * cos(2 * y) + 1)`
- `75x^17 + 25.1x^5 - 35x^4 - 15.2x^3 + 40x^2 - 15.3x + 1`
- `(avg(x,y) <= x + y ? x - y : x * y) + 2.345 * pi / x`
- `while (x <= 100) { x -= 1; }`
- `x <= 'abc123' and (y in 'AString') or ('1x2y3z' != z)`
- `((x + 'abc') like '*123*') or ('a123b' ilike y)`
- `sgn(+1.2^3.4z / -5.6y) <= {-7.8^9 / -10.11x }`

On each sample, Papier updates variables (e.g. x, y, z, u, etc.)
with performance data. Conditionals, trans, trig... go wild!


Available Metrics
-----------------

The backend can pull data from any source defined as a subclass of
the `Metrics` class. This release supports:

* [PAPI][2]: Hardware performance counters.
* Any PAPI predefined, native, or raw perf metric.
See `papi_avail` and `papi_native_avail`.
* TIME: Timers
* WALLCLOCK: application wallclock time.
* CPU: CPU time
* ALLINEA: Metrics gathered from or related to the Allinea MAP tool.
* SAMPLE_COUNT: Number of samples taken so far.
* LOGICAL_CORES: Logical cores as reported by MAP.
* PHYSICAL_CORES: Physical cores as reported by MAP.


Examples
--------

Tested on the Marvel ThunderX2 with PAPI 5.7.0.1.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please just say which version of PAPI you tested with and remove the reference to ThunderX 2.


* Fraction of retired instructions that are floating point or vector instructions:
```
export ALLINEA_PAPIER_EXPRESSION="(PAPI{PAPI_FP_INS} + PAPI{PAPI_VEC_INS}) / PAPI{PAPI_TOT_INS}"
```
* Speculatively executed barrier instructions:
```
export ALLINEA_PAPIER_EXPRESSION="PAPI{ISB_SPEC} + PAPI{DSB_SPEC} + PAPI{DMB_SPEC}"
```
* For the first 200 samples, use perf to measure L1 data cache loads. Then, use PAPI to measure retired branch instructions. (Ok, it's stupid but you get the idea).
```
export ALLINEA_PAPIER_EXPRESSION="$PWD/expression.txt"
cat $ALLINEA_PAPIER_EXPRESSION
var sample_count := ALLINEA{SAMPLE_COUNT};
var result := 0;
if (sample_count < 200) {
result := PAPI{perf::L1-DCACHE-LOADS};
} else {
result := PAPI{BR_RETIRED};
}
result;
```
* Use raw perf events to measure register recycles per thousand instructions (this is how you know you're in the right SMT mode on TX2):
```
export ALLINEA_PAPIER_EXPRESSION="$PWD/expression.txt"
cat $ALLINEA_PAPIER_EXPRESSION
var rob_recycle := PAPI{perf_raw::r0153};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reference a public source for these raw event codes or remove them.

var issq_recycle := PAPI{perf_raw::r0154};
var gpr_recycle := PAPI{perf_raw::r0155};
var fpr_recycle := PAPI{perf_raw::r0156};
var lrq_recycle := PAPI{perf_raw::r0158};
var recycles := rob_recycle + issq_recycle + gpr_recycle + fpr_recycle + lrq_recycle;
var kins := PAPI{PAPI_TOT_INS} / 1000;
recycles / kins;
```
* Instructions per cycle via PAPI alongside MAP's cycles per instruction:
```
export ALLINEA_PAPIER_EXPRESSION="PAPI{PAPI_TOT_INS} / PAPI{PAPI_TOT_CYC}"
```
* Fraction of L2 data accesses that miss alongside total counts of accesses and misses:
```
export ALLINEA_PAPIER_EXPRESSION="PAPI{PAPI_L2_DCM} / PAPI{PAPI_L2_DCA}"
```
* Instructions per cycle per core (TX2 theoretical max is 4):
```
export ALLINEA_PAPIER_EXPRESSION="PAPI{PAPI_TOT_INS} / PAPI{PAPI_TOT_CYC} / PAPI{THREADS_PER_CORE}"
```
* The sine of wallclock time (because why not?):
```
export ALLINEA_PAPIER_EXPRESSION="sin(TIME{WALLCLOCK})"
```
* MAP's sampling frequency (samples per second):
```
export ALLINEA_PAPIER_EXPRESSION="ALLINEA{SAMPLE_COUNT} / TIME{WALLCLOCK}"
```

Troubleshooting
---------------

* What happens if you specify too many counters? You'll get a message on stderr, e.g.
```
[Papier] ERROR: Cannot initialize Papier: Failed to add event 'perf_raw::r015B' to PAPI event set: Event exists, but cannot be counted due to hardware resource limits: Unknown error -8
```

References
----------

[1]: https://github.com/ArashPartow/exprtk
[2]: http://icl.cs.utk.edu/papi/

Loading