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_SOURCE_DIR "${CMAKE_SOURCE_DIR}/test")
|
||||||
set(OVNI_TEST_BUILD_DIR "${CMAKE_BINARY_DIR}/test")
|
set(OVNI_TEST_BUILD_DIR "${CMAKE_BINARY_DIR}/test")
|
||||||
|
|
||||||
macro(ovni_test name driver)
|
include(macros.cmake)
|
||||||
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()
|
|
||||||
|
|
||||||
# Only run performance sensitive tests on Release builds
|
# Only run performance sensitive tests on Release builds
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||||
ovni_test("flush-overhead" "driver.sh")
|
ovni_test(NAME flush-overhead)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
ovni_test("flush" "driver.sh")
|
ovni_test(NAME flush)
|
||||||
ovni_test("mp-simple" "mp-driver.sh")
|
ovni_test(NAME mp-simple MP)
|
||||||
ovni_test("mp-rank" "mp-driver.sh")
|
ovni_test(NAME mp-rank MP)
|
||||||
ovni_test("nosv-nested-tasks" "driver.sh")
|
ovni_test(NAME nosv-nested-tasks)
|
||||||
ovni_test("nosv-nested-tasks-bad" "driver.sh")
|
ovni_test(NAME nosv-nested-tasks-bad
|
||||||
ovni_test("nosv-task-types" "mp-driver.sh")
|
SHOULD_FAIL REGEX "fatal: unknown task type id 1")
|
||||||
ovni_test("nosv-pause" "mp-driver.sh")
|
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
|
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
|
mkdir -p "${workdir}"
|
||||||
NPROCS=4
|
cd "${workdir}"
|
||||||
else
|
|
||||||
NPROCS="$2"
|
|
||||||
fi
|
|
||||||
|
|
||||||
tracedir="ovni"
|
|
||||||
emubin=../ovniemu
|
|
||||||
|
|
||||||
rm -rf "$tracedir"
|
rm -rf "$tracedir"
|
||||||
|
|
||||||
for i in $(seq 1 $NPROCS); do
|
if [ -z "$OVNI_NPROCS" ]; then
|
||||||
# Run the test in the background
|
OVNI_NPROCS=1
|
||||||
OVNI_RANK=$(($i-1)) OVNI_NRANKS=$NPROCS "./$testname" &
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
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
|
# Then launch the emulator in lint mode
|
||||||
"$emubin" -l "$tracedir"
|
"$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
|
# 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
|
# 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
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# 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"
|
function(nosv_test)
|
||||||
tracedir="ovni"
|
ovni_test(${ARGN})
|
||||||
emubin=../ovniemu
|
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"
|
nosv_test(NAME nosv-attach SOURCE nosv/attach.c)
|
||||||
|
|
||||||
# Run the test
|
|
||||||
"./$testname"
|
|
||||||
|
|
||||||
# Then launch the emulator in lint mode
|
|
||||||
"$emubin" -l "$tracedir"
|
|
||||||
|
|
||||||
#rm -rf $tracedir
|
|
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