diff --git a/configure.sh b/configure.sh index 4d0eb766dd95ecd6374176cc30933eefe10872ab..db57e5a95a7228663a2c7a34ae66b9507aa72c26 100755 --- a/configure.sh +++ b/configure.sh @@ -130,9 +130,14 @@ detect_caps() { if [ -e /usr/local/cuda/lib64 ] && [ -e /usr/local/cuda/include ]; then hdr_whitelist="${hdr_whitelist}|nvidia_gpu" - NVML_LDFLAGS='-L/usr/local/cuda/lib64 -lnvidia-ml' + CAPTOR_LDFLAGS="${CAPTOR_LDFLAGS} -L/usr/local/cuda/lib64 -lnvidia-ml" NVML_IFLAGS='-I/usr/local/cuda/include' fi + if [ `/sbin/ldconfig -p | grep liblikwid | wc -l` -ge 1 ]; then + hdr_whitelist="${hdr_whitelist}|likwid" + CAPTOR_LDFLAGS="${CAPTOR_LDFLAGS} -llikwid" + fi + vendor=$(awk '/vendor_id/ {print $3; exit}' /proc/cpuinfo) vendor_lc=$(echo "$vendor" | tr 'A-Z' 'a-z') @@ -157,7 +162,7 @@ detect_caps() { case $1 in --all | -a) all=1 - NVML_LDFLAGS="-L/usr/local/cuda/lib64 -lnvidia-ml" + CAPTOR_LDFLAGS="-L/usr/local/cuda/lib64 -lnvidia-ml -llikwid" NVML_IFLAGS="-I/usr/local/cuda/include" ;; --unique | -u) @@ -209,7 +214,7 @@ fi try gen_sensors_h "$sensors" "$nb_sensors" >"$target_hdr" try gen_sensors_mk "$sensors" >"$target_mk" -try printf "NVML_LDFLAGS = %s\n" "$NVML_LDFLAGS" >>"$target_mk" +try printf "CAPTOR_LDFLAGS = %s\n" "$CAPTOR_LDFLAGS" >>"$target_mk" try printf "NVML_IFLAGS = %s\n" "$NVML_IFLAGS" >>"$target_mk" printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 diff --git a/makefile b/makefile index 4dcbce48455abcce4d567201af99f7fb24a39552..93b32d2e95e2ea94ccb56ac7c7c4db6d6a179af6 100644 --- a/makefile +++ b/makefile @@ -13,14 +13,14 @@ PREFIX = /usr/local CC = gcc CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib $(NVML_IFLAGS) CFLAGS = $(CPPFLAGS) -O3 -Werror -LDFLAGS = $(NVML_LDFLAGS) +LDFLAGS = $(CAPTOR_LDFLAGS) ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q all: $(BIN) man CAPTOR_OBJ = -NVML_LDFLAGS = +CAPTOR_LDFLAGS = NVML_IFLAGS = include ./sensors.mk diff --git a/src/likwid.c b/src/likwid.c new file mode 100644 index 0000000000000000000000000000000000000000..bf1ea148a89e239e58c8a13fb9b4f2ed192d752a --- /dev/null +++ b/src/likwid.c @@ -0,0 +1,193 @@ +/******************************************************* + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <stdint.h> +#include <asm/unistd.h> +#include <stdint.h> + +#include <likwid.h> + +#include "util.h" + + +struct Likwid { + int nbcores; + int gid; + int nbperf; + char **labels; +}; +typedef struct Likwid Likwid; + + + +void _get_likwid(Likwid *likwid, uint64_t *values) +{ + int err; + if ((err=perfmon_readCounters()) < 0) { + printf("Failed to read counters for group %d for thread %d\n",likwid->gid, (-1*err)-1); + perfmon_finalize(); + topology_finalize(); + exit(1); + } + + for (int i = 0; i < likwid->nbperf; i++) { + uint64_t accu = 0; + for (int core = 0; core < likwid->nbcores; core++) { + accu += perfmon_getLastResult(likwid->gid, i, core); + } + values[i] = accu; + } +} + +void label_likwid(char **labels, void *ptr) +{ + Likwid *state = (Likwid *) ptr; + + for (int i = 0; i < state->nbperf; i++) { + labels[i] = state->labels[i]; + } +} + +void *show_all_likwid(void *none1, size_t none2) +{ + execlp("likwid-perfctr", "likwid-perfctr", "-e", NULL); + UNUSED(none1); + UNUSED(none2); + /* Should not be executed */ + printf("Likwid not available\n"); + exit(EXIT_FAILURE); + return NULL; /* not reached */ +} + + + +unsigned int init_likwid(char *args, void **state) +{ + Likwid *likwid = malloc(sizeof(struct Likwid)); + likwid->nbperf = 0; + likwid->labels = NULL; + + char *events = malloc(sizeof(char)*strlen(args)+1); + strcpy(events, args); + while(events != NULL) { + likwid->nbperf++; + likwid->labels = realloc(likwid->labels, sizeof(char*)*likwid->nbperf); + likwid->labels[likwid->nbperf-1] = events; + events = index(events, ','); + if(events != NULL) { + events[0] = '\0'; + events++; + } + } + + if (topology_init() < 0) { + perror("Failed to initialize LIKWID's topology module\n"); + exit(1); + } + CpuTopology_t topology = get_cpuTopology(); + likwid->nbcores = topology->numHWThreads; + + // Create affinity domains. Commonly only needed when reading Uncore counters + affinity_init(); + + int* cpus = (int*)malloc(likwid->nbcores * sizeof(int)); + for (int i=0;i<likwid->nbcores;i++) + cpus[i] = topology->threadPool[i].apicId; + // accessClient_setaccessmode(0); + HPMmode(-1); + if (perfmon_init(likwid->nbcores, cpus) < 0) { + topology_finalize(); + perror("perfmon_init"); + exit(1); + } + free(cpus); + + // Add eventset string to the perfmon module. + putenv("LIKWID_FORCE=1"); + likwid->gid = perfmon_addEventSet(args); + if (likwid->gid < 0) { + printf("perfmon_addEventSet with %s\n", args); + perfmon_finalize(); + topology_finalize(); + exit(1); + } + + // Setup the eventset identified by group ID (gid). + if (perfmon_setupCounters(likwid->gid) < 0) { + perfmon_finalize(); + topology_finalize(); + perror("perfmon_setupCounters"); + exit(1); + } + // Start all counters in the previously set up event set. + if (perfmon_startCounters() < 0) { + perfmon_finalize(); + topology_finalize(); + perror("perfmon_startCounters"); + exit(1); + } + + *state = (void *) likwid; + + return likwid->nbperf; +} + + + + + +void clean_likwid(void *ptr) +{ + Likwid *likwid = (Likwid *) ptr; + + free(likwid->labels); + free(likwid); + + perfmon_stopCounters(); + + perfmon_finalize(); + affinity_finalize(); + topology_finalize(); +} + + + + + + + + + + + +unsigned int get_likwid(uint64_t *results, void *ptr) +{ + Likwid *state = (Likwid *) ptr; + + _get_likwid(state, results); + + return state->nbperf; +} + diff --git a/src/likwid.h b/src/likwid.h new file mode 100644 index 0000000000000000000000000000000000000000..dccf7a4d8ff066d1a127f0abf739a02334cfbc66 --- /dev/null +++ b/src/likwid.h @@ -0,0 +1,54 @@ +/******************************************************* + Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_likwid(char *, void **); +unsigned int get_likwid(uint64_t *results, void *); +void clean_likwid(void *); +void label_likwid(char **labels, void *); +void *show_all_likwid(void *, size_t); + +Sensor likwid = { + .init = init_likwid, + .get = get_likwid, + .clean = clean_likwid, + .label = label_likwid, + .nb_opt = 2, +}; + +Optparse likwid_opt[2] = { + { + .longname = "likwid", + .shortname = 'k', + .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<perf_list>", + .usage_msg = "performance counters\n" + "\tperf_list is a coma separated list of performance counters with associated register.\n" + "\tEx: FP_ARITH_INST_RETIRED_128B_PACKED_DOUBLE:PMC0,FP_ARITH_INST_RETIRED_SCALAR_DOUBLE:PMC1", + }, + { + .longname = "list-likwid", + .shortname = 'w', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "list the available performance counters and quit", + .fn = show_all_likwid, + }, +}; +