Add support for runtime tests
This commit is contained in:
parent
158f2b6ea6
commit
c3c7aa730e
67
nix/nosv.nix
Normal file
67
nix/nosv.nix
Normal file
@ -0,0 +1,67 @@
|
||||
# Build with `nix-build nix/old-glibc.nix`
|
||||
let
|
||||
# Pin the nixpkgs
|
||||
nixpkgsPath = builtins.fetchTarball {
|
||||
# Descriptive name to make the store path easier to identify
|
||||
name = "nixos-20.09";
|
||||
# Commit hash for nixos-20.09 as of 2021-01-11
|
||||
url = "https://github.com/nixos/nixpkgs/archive/41dddb1283733c4993cb6be9573d5cef937c1375.tar.gz";
|
||||
# Hash obtained using `nix-prefetch-url --unpack <url>`
|
||||
sha256 = "1blbidbmxhaxar2x76nz72bazykc5yxi0algsbrhxgrsvijs4aiw";
|
||||
};
|
||||
|
||||
pkgs = import nixpkgsPath { };
|
||||
|
||||
ovni = pkgs.stdenv.mkDerivation rec {
|
||||
name = "ovni";
|
||||
|
||||
buildInputs = with pkgs; [ cmake openmpi ];
|
||||
|
||||
# Prevent accidental reutilization of previous builds, as we are taking the
|
||||
# current directory as-is
|
||||
preConfigure = ''
|
||||
rm -rf build install
|
||||
|
||||
# There is no /bin/bash
|
||||
patchShebangs test/*.sh
|
||||
'';
|
||||
|
||||
cmakeBuildType = "Debug";
|
||||
cmakeFlags = [ "-DCMAKE_SKIP_BUILD_RPATH=OFF" ];
|
||||
buildFlags = [ "VERBOSE=1" ];
|
||||
preCheck = ''
|
||||
export CTEST_OUTPUT_ON_FAILURE=1
|
||||
'';
|
||||
dontStrip = true;
|
||||
doCheck = true;
|
||||
checkTarget = "test";
|
||||
|
||||
src = ../.;
|
||||
};
|
||||
|
||||
nosv = pkgs.stdenv.mkDerivation rec {
|
||||
pname = "nosv";
|
||||
version = src.shortRev;
|
||||
buildInputs = with pkgs; [ autoreconfHook pkg-config numactl ovni ];
|
||||
configureFlags = [ "--with-ovni=${ovni}" ];
|
||||
dontStrip = true;
|
||||
src = builtins.fetchGit {
|
||||
url = "ssh://git@gitlab-internal.bsc.es/nos-v/nos-v.git";
|
||||
ref = "master";
|
||||
};
|
||||
};
|
||||
|
||||
# Quick fix to avoid rebuilding every time the ovni source changes.
|
||||
# Use this nosv' version below as dependency of ovni-rt
|
||||
nosv' = /nix/store/rvnrbc7ibpw06jdilz6mha7szzxcr2mi-nosv-8936f3e;
|
||||
|
||||
ovni-rt = ovni.overrideAttrs (old: {
|
||||
__impure = true;
|
||||
__noChroot = true;
|
||||
buildInputs = old.buildInputs ++ [ nosv pkgs.strace ];
|
||||
cmakeFlags = old.cmakeFlags ++ [ "-DBUILD_RT_TESTING=ON" ];
|
||||
});
|
||||
|
||||
in
|
||||
|
||||
ovni-rt
|
@ -17,31 +17,22 @@
|
||||
set(OVNI_TEST_SOURCE_DIR "${CMAKE_SOURCE_DIR}/test")
|
||||
set(OVNI_TEST_BUILD_DIR "${CMAKE_BINARY_DIR}/test")
|
||||
|
||||
macro(ovni_test name driver)
|
||||
add_executable("${name}" "${name}.c")
|
||||
target_link_libraries("${name}" ovni)
|
||||
|
||||
add_test(NAME "${name}"
|
||||
COMMAND "${OVNI_TEST_SOURCE_DIR}/${driver}" "${name}"
|
||||
WORKING_DIRECTORY "${OVNI_TEST_BUILD_DIR}")
|
||||
|
||||
set_property(TEST "${name}" PROPERTY RUN_SERIAL TRUE)
|
||||
|
||||
if("${name}" MATCHES ".*-bad")
|
||||
set_property(TEST "${name}" PROPERTY WILL_FAIL TRUE)
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
include(macros.cmake)
|
||||
|
||||
# Only run performance sensitive tests on Release builds
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
ovni_test("flush-overhead" "driver.sh")
|
||||
ovni_test(NAME flush-overhead)
|
||||
endif()
|
||||
|
||||
ovni_test("flush" "driver.sh")
|
||||
ovni_test("mp-simple" "mp-driver.sh")
|
||||
ovni_test("mp-rank" "mp-driver.sh")
|
||||
ovni_test("nosv-nested-tasks" "driver.sh")
|
||||
ovni_test("nosv-nested-tasks-bad" "driver.sh")
|
||||
ovni_test("nosv-task-types" "mp-driver.sh")
|
||||
ovni_test("nosv-pause" "mp-driver.sh")
|
||||
ovni_test(NAME flush)
|
||||
ovni_test(NAME mp-simple MP)
|
||||
ovni_test(NAME mp-rank MP)
|
||||
ovni_test(NAME nosv-nested-tasks)
|
||||
ovni_test(NAME nosv-nested-tasks-bad
|
||||
SHOULD_FAIL REGEX "fatal: unknown task type id 1")
|
||||
ovni_test(NAME nosv-task-types MP)
|
||||
ovni_test(NAME nosv-pause MP)
|
||||
|
||||
if(BUILD_RT_TESTING)
|
||||
add_subdirectory(rt)
|
||||
endif()
|
||||
|
70
test/macros.cmake
Normal file
70
test/macros.cmake
Normal file
@ -0,0 +1,70 @@
|
||||
include(CMakeParseArguments)
|
||||
|
||||
function(ovni_test)
|
||||
set(switches MP SHOULD_FAIL)
|
||||
set(single NPROC NAME REGEX)
|
||||
set(multi SOURCE ENV)
|
||||
|
||||
cmake_parse_arguments(
|
||||
OVNI_TEST "${switches}" "${single}" "${multi}" ${ARGN})
|
||||
|
||||
if(NOT OVNI_TEST_NAME)
|
||||
message(FATAL_ERROR "You must provide a test NAME")
|
||||
endif(NOT OVNI_TEST_NAME)
|
||||
|
||||
set(OVNI_TEST_NAME ${OVNI_TEST_NAME} PARENT_SCOPE)
|
||||
|
||||
# Set default source if not given
|
||||
if(NOT OVNI_TEST_SOURCE)
|
||||
set(OVNI_TEST_SOURCE "${OVNI_TEST_NAME}.c")
|
||||
#message("Setting default source to ${OVNI_TEST_SOURCE}")
|
||||
endif()
|
||||
|
||||
if(NOT OVNI_TEST_NPROC)
|
||||
if(NOT OVNI_TEST_MP)
|
||||
set(OVNI_TEST_NPROC 1)
|
||||
else()
|
||||
set(OVNI_TEST_NPROC 4)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND OVNI_TEST_ENV
|
||||
"OVNI_NPROCS=${OVNI_TEST_NPROC}")
|
||||
|
||||
list(APPEND OVNI_TEST_ENV
|
||||
"OVNI_BUILD_DIR=${CMAKE_BINARY_DIR}")
|
||||
|
||||
list(APPEND OVNI_TEST_ENV
|
||||
"OVNI_CURRENT_DIR=${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
add_executable("${OVNI_TEST_NAME}" "${OVNI_TEST_SOURCE}")
|
||||
target_link_libraries("${OVNI_TEST_NAME}" ovni)
|
||||
|
||||
set(driver "${OVNI_TEST_SOURCE_DIR}/ovni-driver.sh")
|
||||
|
||||
if(OVNI_TEST_SHOULD_FAIL)
|
||||
if(NOT OVNI_TEST_REGEX)
|
||||
message(FATAL_ERROR "You must provide a REGEX for a failing test")
|
||||
endif()
|
||||
# Custom error handler, as ctest doesn't behave as one would expect.
|
||||
add_test(NAME "${OVNI_TEST_NAME}"
|
||||
COMMAND
|
||||
"${OVNI_TEST_SOURCE_DIR}/match-error.sh"
|
||||
"${OVNI_TEST_REGEX}"
|
||||
"${driver}"
|
||||
"${OVNI_TEST_NAME}"
|
||||
WORKING_DIRECTORY "${OVNI_TEST_BUILD_DIR}")
|
||||
else()
|
||||
add_test(NAME "${OVNI_TEST_NAME}"
|
||||
COMMAND
|
||||
"${driver}"
|
||||
"${OVNI_TEST_NAME}"
|
||||
WORKING_DIRECTORY "${OVNI_TEST_BUILD_DIR}")
|
||||
endif()
|
||||
|
||||
set_tests_properties("${OVNI_TEST_NAME}"
|
||||
PROPERTIES
|
||||
RUN_SERIAL TRUE
|
||||
ENVIRONMENT "${OVNI_TEST_ENV}"
|
||||
WORKING_DIRECTORY "${OVNI_TEST_BUILD_DIR}")
|
||||
endfunction(ovni_test)
|
29
test/match-error.sh
Executable file
29
test/match-error.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script return 0 if and only if the given program returns non-zero
|
||||
# AND the regex matches the output
|
||||
|
||||
# $1 = the regex as grep
|
||||
# $2... The program
|
||||
|
||||
regex="$1"
|
||||
shift
|
||||
|
||||
"${@}" 2>&1 | stdbuf -i0 -o0 tee /dev/stderr | grep -q "${regex}"
|
||||
|
||||
rcprog=${PIPESTATUS[0]} rcgrep=${PIPESTATUS[2]}
|
||||
|
||||
echo "rcprog='$rcprog' rcgrep='$rcgrep'"
|
||||
|
||||
if [ "$rcprog" != 0 ] && [ "$rcgrep" = 0 ]; then
|
||||
echo "ok: program failed and grep matched the error line"
|
||||
exit 0
|
||||
else
|
||||
if [ "$rcprog" = 0 ]; then
|
||||
echo "error: program exited with 0 rather than failure"
|
||||
fi
|
||||
if [ "$rcgrep" != 0 ]; then
|
||||
echo "error: regex \"${regex}\" not matched"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
@ -17,25 +17,30 @@
|
||||
|
||||
set -e
|
||||
|
||||
testname="$1"
|
||||
dir=$(readlink -f "${OVNI_CURRENT_DIR}")
|
||||
testname="$dir/$1"
|
||||
workdir="${testname}.trace"
|
||||
tracedir="${workdir}/ovni"
|
||||
emubin="${OVNI_BUILD_DIR}/ovniemu"
|
||||
|
||||
if [ -z "$2" ]; then
|
||||
NPROCS=4
|
||||
else
|
||||
NPROCS="$2"
|
||||
fi
|
||||
|
||||
tracedir="ovni"
|
||||
emubin=../ovniemu
|
||||
mkdir -p "${workdir}"
|
||||
cd "${workdir}"
|
||||
|
||||
rm -rf "$tracedir"
|
||||
|
||||
for i in $(seq 1 $NPROCS); do
|
||||
# Run the test in the background
|
||||
OVNI_RANK=$(($i-1)) OVNI_NRANKS=$NPROCS "./$testname" &
|
||||
done
|
||||
if [ -z "$OVNI_NPROCS" ]; then
|
||||
OVNI_NPROCS=1
|
||||
fi
|
||||
|
||||
wait
|
||||
if [ "$OVNI_NPROCS" -gt 1 ]; then
|
||||
for i in $(seq 1 "$OVNI_NPROCS"); do
|
||||
# Run the test in the background
|
||||
OVNI_RANK=$(($i-1)) OVNI_NRANKS=$OVNI_NPROCS "$testname" &
|
||||
done
|
||||
wait
|
||||
else
|
||||
"$testname"
|
||||
fi
|
||||
|
||||
# Then launch the emulator in lint mode
|
||||
"$emubin" -l "$tracedir"
|
28
test/driver.sh → test/rt/CMakeLists.txt
Executable file → Normal file
28
test/driver.sh → test/rt/CMakeLists.txt
Executable file → Normal file
@ -1,6 +1,5 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2021 Barcelona Supercomputing Center (BSC)
|
||||
# Copyright (c) 2022 Barcelona Supercomputing Center (BSC)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,18 +14,17 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
set -e
|
||||
find_library(nosv libnosv)
|
||||
find_path(NOSV_INCLUDE_DIR nosv.h)
|
||||
|
||||
testname="$1"
|
||||
tracedir="ovni"
|
||||
emubin=../ovniemu
|
||||
function(nosv_test)
|
||||
ovni_test(${ARGN})
|
||||
target_link_libraries("${OVNI_TEST_NAME}" nosv)
|
||||
target_include_directories("${OVNI_TEST_NAME}"
|
||||
PUBLIC ${NOSV_INCLUDE_DIR})
|
||||
set_property(TEST "${OVNI_TEST_NAME}" APPEND
|
||||
PROPERTY
|
||||
ENVIRONMENT "NOSV_CONFIG=${OVNI_TEST_SOURCE_DIR}/rt/nosv.toml")
|
||||
endfunction()
|
||||
|
||||
rm -rf "$tracedir"
|
||||
|
||||
# Run the test
|
||||
"./$testname"
|
||||
|
||||
# Then launch the emulator in lint mode
|
||||
"$emubin" -l "$tracedir"
|
||||
|
||||
#rm -rf $tracedir
|
||||
nosv_test(NAME nosv-attach SOURCE nosv/attach.c)
|
90
test/rt/nosv.toml
Normal file
90
test/rt/nosv.toml
Normal file
@ -0,0 +1,90 @@
|
||||
# This file is part of nOS-V and is licensed under the terms contained in the COPYING file
|
||||
#
|
||||
# Copyright (C) 2021-2022 Barcelona Supercomputing Center (BSC)
|
||||
|
||||
# Default nOS-V configuration file.
|
||||
# Note that every process in the same nOS-V instance should load an identical configuration file,
|
||||
# otherwise, the behaviour is unspecified
|
||||
|
||||
# Shared memory configuration
|
||||
[shared_memory]
|
||||
# Name of the shared memory section. This can be leveraged to create two separate nOS-V instances
|
||||
# in the same system. Generally this has to remain unchanged
|
||||
name = "nosv"
|
||||
# Size of the shared memory section. Choose powers of two
|
||||
size = "2G"
|
||||
# Start of the shared memory mapping
|
||||
# This option should be memory address codified in hexadecimal (start with 0x)
|
||||
start = 0x0000200000000000
|
||||
|
||||
# Scheduler configuration
|
||||
# These parameters allow to fine tune the scheduler's behaviour
|
||||
[scheduler]
|
||||
# Number of logical CPUs mapped to a single scheduler SPSC for ready tasks
|
||||
# Minimum is 1, there is no maximum. Try to choose numbers that divide evenly the number
|
||||
# of CPUs in the system.
|
||||
# A lower number will yield more scheduling throughput and is adequate when using
|
||||
# multiple task creator processes.
|
||||
# A higher number will yield lower scheduling latency and is adequate when using one or few
|
||||
# task creator processes
|
||||
cpus_per_queue = 1
|
||||
# Number of tasks that are grabbed off of a queue when processing ready tasks.
|
||||
# Lowering the number may be better if there are very few ready tasks during execution.
|
||||
# Increasing the batch may help if your CPU has bad single-thread performance.
|
||||
# In general, the default value of 64 should result in a good trade-off
|
||||
queue_batch = 64
|
||||
# Scheduler quantum in ns. This is a guideline for how long should we execute one process' tasks
|
||||
# until we have to switch to the next one. However, as nOS-V tasks are not preemptable, it isn't enforced.
|
||||
# This parameter is specially relevant for the nosv_schedpoint function, which will try to schedule
|
||||
# each quantum ns.
|
||||
# A lower value will cause more inter-process context switches but may provide more uniform progress,
|
||||
# while a higher value will minimize context switches but may stall applications for longer
|
||||
quantum_ns = 20000000 # nanoseconds
|
||||
# Size of the queues that are used to place tasks into the scheduler
|
||||
# A good value should be a multiple of queue_batch
|
||||
in_queue_size = 256
|
||||
|
||||
# CPU Governor configuration
|
||||
# Controls the policy that nOS-V follows to block idle CPUs to save energy and resources
|
||||
[governor]
|
||||
# There is a choice between three different governor policies:
|
||||
# - hybrid: CPUs will spin for governor.spins before going to sleep when no work is available
|
||||
# - idle: CPUs will sleep immediately when no work is available
|
||||
# - busy: CPUs will never sleep
|
||||
# In general, use idle when targeting minimum power usage, and busy when targeting maximum performance
|
||||
# The default is hybrid as it provides a good balance between power and performance.
|
||||
policy = "hybrid"
|
||||
# Number of times a CPU will spin without sleeping in the "hybrid" policy.
|
||||
# When "idle" or "busy" are selected, this setting is ignored
|
||||
spins = 10000
|
||||
|
||||
# Debug options
|
||||
[debug]
|
||||
# Dump all the configuration options nOS-V is running with, its final parsed values and the
|
||||
# path of the config file being used
|
||||
dump_config = false
|
||||
|
||||
# Hardware Counters configuration
|
||||
[hwcounters]
|
||||
# Whether to print verbose information if a backend is enabled
|
||||
verbose = false
|
||||
# The enabled HWCounter backends. Possible options: "papi", "none"
|
||||
backend = "none"
|
||||
# The list of PAPI counters to read. By default only "PAPI_TOT_INS" and "PAPI_TOT_CYC"
|
||||
papi_events = [
|
||||
"PAPI_TOT_INS",
|
||||
"PAPI_TOT_CYC"
|
||||
]
|
||||
|
||||
# Enabling turbo will cause nOS-V to set architecture-specific optimization flags on every created
|
||||
# or attached threads. In x86, this will cause the FTZ and DAZ flags of the SSE FPU to be enabled,
|
||||
# causing a significant performance increase in floating-point applications, but disabling IEEE-754
|
||||
# compatibility.
|
||||
[turbo]
|
||||
enabled = false
|
||||
|
||||
# Monitoring cappabilities and configuration.
|
||||
[monitoring]
|
||||
enabled = false
|
||||
# Whether to print verbose information if monitoring is enabled
|
||||
verbose = false
|
33
test/rt/nosv/attach.c
Normal file
33
test/rt/nosv/attach.c
Normal file
@ -0,0 +1,33 @@
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <unistd.h>
|
||||
#include <nosv.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
nosv_init();
|
||||
|
||||
nosv_task_type_t type;
|
||||
if(nosv_type_init(&type, NULL, NULL, NULL, "adopted", NULL,
|
||||
NULL, NOSV_TYPE_INIT_EXTERNAL) != 0)
|
||||
die("nosv_type_init failed\n");
|
||||
|
||||
nosv_task_t task;
|
||||
if(nosv_attach(&task, type, 0, NULL, 0) != 0)
|
||||
die("nosv_attach failed\n");
|
||||
|
||||
usleep(100);
|
||||
|
||||
if(nosv_detach(0) != 0)
|
||||
die("nosv_detach failed\n");
|
||||
|
||||
if(nosv_type_destroy(type, 0) != 0)
|
||||
die("nosv_type_destroy failed\n");
|
||||
|
||||
if(nosv_shutdown() != 0)
|
||||
die("nosv_shutdown failed\n");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user