The instrumentation scenarios are listed below, covering the most common situations.
So far you have the Linux kernel source tree and the PMUv3 plugin source code.
Next, create a third directory to learn how to integrate the PMUv3 plugin into an application as follows:
cd ../ ; mkdir test ; cd test
The instructions assume you have all three directories in parallel. If you have a different directory structure, you may need to adjust the build commands to find the header files and libraries.
Here are the 3 directories you now have:
./linux
./PMUv3_plugin
./test
You can use the test directory to try out the integration scenarios.
The first scenario is to instrument a single section of code in C.
The general process to instrument code includes the following steps:
pmuv3_bundle_init()
with the bundle number as an argumentprocess_start_count()
process_end_count()
to stop countingpost_process()
with the same bundle numbershutdown_resources()
As an example, use a text editor to create a file test1.c
in the test
directory with the contents below:
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include "pmuv3_plugin_bundle.h"
#include "processing.h"
#define VECTOR_SIZE 10000
void initialize_vectors(double vector_a[], double vector_b[], int size) {
for (int i = 0; i < size; i++) {
vector_a[i] = sin(i);
vector_b[i] = cos(i);
}
}
void calculate_result(double result[], double vector_a[], double vector_b[], int size) {
for (int i = 0; i < size; i++) {
result[i] = vector_a[i] + vector_b[i];
}
}
int main(int argc, char **argv) {
int bundle_number;
struct CountData counter_data;
/* Bundle number is passed as an argument */
if (argc != 2) {
fprintf(stderr, "Usage: %s <bundle number>\n", argv[0]);
return EXIT_FAILURE;
}
bundle_number = atoi(argv[1]);
/* Initialize the bundle of events */
if (pmuv3_bundle_init(bundle_number) != 0) {
fprintf(stderr, "Failed to initialize PMU bundle\n");
return EXIT_FAILURE;
}
/* Code to be analyzed */
process_start_count(&counter_data);
/* Declare vectors */
double vector_a[VECTOR_SIZE], vector_b[VECTOR_SIZE], result[VECTOR_SIZE];
/* Initialize and calculate vectors */
initialize_vectors(vector_a, vector_b, VECTOR_SIZE);
calculate_result(result, vector_a, vector_b, VECTOR_SIZE);
process_end_count(&counter_data);
/* Write CSV file and clean up */
post_process(bundle_number);
shutdown_resources();
return EXIT_SUCCESS;
}
The include files and function calls are added in the code to provide the performance instrumentation.
Build the application as follows:
gcc -I ../linux/tools/lib/perf/include -I ../PMUv3_plugin/ test1.c -o test1 -L ../PMUv3_plugin/ -lpmuv3_plugin_bundle -lperf -lapi -lm
Run the application and pass the bundle number of 4 (to capture stall information):
sudo ./test1 4
The output prints the following:
- running pmuv3_plugin_bundle.c...OK
End is 1404713, Start is 119346
End is 112270, Start is 43884
End is 285708, Start is 6714
The results are captured in the file bundle4.csv
.
Display the text file to see the contents:
cat bundle4.csv
The data shows the metrics on the first line and the values on the second line as shown below:
CPU_CYCLES,STALL_FRONTEND,STALL_BACKEND
1285367,68386,278994
You can quickly collect the data for all bundles. Save the code below in a file named run.sh
:
#!/bin/bash
for i in {0..14}
do
echo $i
sudo ./test1 $i
done
Run the script:
bash ./run.sh
All 15 of the bundle CSV files have been generated.
Next, learn how you can visualize the data.