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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user