diff options
Diffstat (limited to 'tools/runtime-env')
-rw-r--r-- | tools/runtime-env/Makefile.am | 11 | ||||
-rw-r--r-- | tools/runtime-env/Makefile.in | 592 | ||||
-rw-r--r-- | tools/runtime-env/README.md | 95 | ||||
-rw-r--r-- | tools/runtime-env/main.cpp | 496 |
4 files changed, 1194 insertions, 0 deletions
diff --git a/tools/runtime-env/Makefile.am b/tools/runtime-env/Makefile.am new file mode 100644 index 0000000..3ee3569 --- /dev/null +++ b/tools/runtime-env/Makefile.am @@ -0,0 +1,11 @@ + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include + +EXTRA_PROGRAMS = \ + runtime-env + +CLEANFILES = \ + runtime-env + +runtime_env_SOURCES = main.cpp diff --git a/tools/runtime-env/Makefile.in b/tools/runtime-env/Makefile.in new file mode 100644 index 0000000..83dcf1c --- /dev/null +++ b/tools/runtime-env/Makefile.in @@ -0,0 +1,592 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +EXTRA_PROGRAMS = runtime-env$(EXEEXT) +subdir = tools/runtime-env +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/m4_ax_valgrind_check.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am_runtime_env_OBJECTS = main.$(OBJEXT) +runtime_env_OBJECTS = $(am_runtime_env_OBJECTS) +runtime_env_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/main.Po +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(runtime_env_SOURCES) +DIST_SOURCES = $(runtime_env_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = check-valgrind-recursive \ + check-valgrind-memcheck-recursive \ + check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ + check-valgrind-sgcheck-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + README.md +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +API_VERSION = @API_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_NODEBUG = @CPPFLAGS_NODEBUG@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CXXFLAGS_UNITTESTS = @CXXFLAGS_UNITTESTS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ +ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ +ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ +ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +EXPECT = @EXPECT@ +GDB = @GDB@ +HAVE_CXX17 = @HAVE_CXX17@ +INCDIR = @INCDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MISCDIR = @MISCDIR@ +MKDIR_P = @MKDIR_P@ +OBJDIR = @OBJDIR@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +QUICKCHECKDIR = @QUICKCHECKDIR@ +RUNTEST_BIN = @RUNTEST_BIN@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX = @SPHINX@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VALGRIND_ENABLED = @VALGRIND_ENABLED@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +valgrind_enabled_tools = @valgrind_enabled_tools@ +valgrind_tools = @valgrind_tools@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include + +CLEANFILES = \ + runtime-env + +runtime_env_SOURCES = main.cpp +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/runtime-env/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tools/runtime-env/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +runtime-env$(EXEEXT): $(runtime_env_OBJECTS) $(runtime_env_DEPENDENCIES) $(EXTRA_runtime_env_DEPENDENCIES) + @rm -f runtime-env$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(runtime_env_OBJECTS) $(runtime_env_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +check-valgrind-local: +check-valgrind-memcheck-local: +check-valgrind-helgrind-local: +check-valgrind-drd-local: +check-valgrind-sgcheck-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +check-valgrind: check-valgrind-am + +check-valgrind-am: check-valgrind-local + +check-valgrind-drd: check-valgrind-drd-am + +check-valgrind-drd-am: check-valgrind-drd-local + +check-valgrind-helgrind: check-valgrind-helgrind-am + +check-valgrind-helgrind-am: check-valgrind-helgrind-local + +check-valgrind-memcheck: check-valgrind-memcheck-am + +check-valgrind-memcheck-am: check-valgrind-memcheck-local + +check-valgrind-sgcheck: check-valgrind-sgcheck-am + +check-valgrind-sgcheck-am: check-valgrind-sgcheck-local + +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/main.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/main.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am \ + check-valgrind-am check-valgrind-drd-am \ + check-valgrind-drd-local check-valgrind-helgrind-am \ + check-valgrind-helgrind-local check-valgrind-local \ + check-valgrind-memcheck-am check-valgrind-memcheck-local \ + check-valgrind-sgcheck-am check-valgrind-sgcheck-local clean \ + clean-generic cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tools/runtime-env/README.md b/tools/runtime-env/README.md new file mode 100644 index 0000000..043d225 --- /dev/null +++ b/tools/runtime-env/README.md @@ -0,0 +1,95 @@ +runtime-env +=========== + +This tools performs some benchmarks to determine the optimal loop-unrolling factor +combined with SIMD features (if available) for `mdds::multi_type_vector`. + +Build +----- + +You can build this tool in one of two ways, as illustrated below. + +### Autotools + +First, run `./autogen.sh` at the project root directory while passing your desired +compiler flags via `CXXFLAGS` environment variable, like below: + +``` +CXXFLAGS="-O3 -march=native -DNDEBUG" ./autogen.sh +``` +In this example we are using `gcc`, and by specifying `-march=native` it uses +the architecture type in the current environment as its target. Then change +directory into `tools/runtime-env`, and run `make runtime-env` to build the program: + +``` +cd tools/runtime-env +make runtime-env +``` + +### CMake + +To specify custom compiler flags in cmake, run with `cmake -E env CXXFLAGS="..."` +followed by the usual cmake configuration command. Here is an example of specifying +`-O3 -march=native -DNDEBUG` as the compiler flags to cmake: + +``` +mkdir build +cd build +cmake -E env CXXFLAGS="-O3 -march=native -DNDEBUG" cmake .. +``` + +Once the build configuration step is finished, build the tool by + +``` +cmake --build . --target runtime-env +``` +or simply + +``` +make runtime-env +``` + +if you use GNU Make as your backend. The program will be built at `./tools/runtime-env/runtime-env`. + +Run it +------ + +To run the tool, simply execute it with no arguments. It should show you a progress +bar indicating that it's performing benchmarks. Once finished, it should display an +ASCII chart similar to the following: + +``` + Category | Average duration (seconds) +---------------+--------------------------------------------------------> +(SoA, 16) | ooooooooooooo 0.04123 +(SoA, 32) | oooooooooooooo 0.04409 +(SoA, 08) | oooooooooooooooo 0.05151 +(AoS, 08) | ++++++++++++++++++ 0.05712 +(AoS, 16) | ++++++++++++++++++ 0.05799 +(AoS, 04) | ++++++++++++++++++ 0.0584 +(SoA, sse2+16) | ooooooooooooooooooo 0.06204 +(AoS, 32) | ++++++++++++++++++++ 0.06285 +(SoA, sse2+08) | oooooooooooooooooooo 0.06412 +(SoA, sse2+04) | ooooooooooooooooooooo 0.0673 +(SoA, 00) | ooooooooooooooooooooo 0.06833 +(SoA, 04) | ooooooooooooooooooooooo 0.07281 +(SoA, sse2+00) | ooooooooooooooooooooooooooooo 0.09283 +(AoS, 00) | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 0.1712 + +Storage of SoA with the LU factor of 16 appears to be the best choice +in this environment. +``` + +What the chart shows are the average durations for some artificially created +block position adjustment tasks, and fewer the number the better. The results +are sorted in ascending order, so the item at the very top is considered to be +the most optimum choice in the current run-time environment. + +The program also generates the following files: + +* graph-output.txt +* raw-data.csv + +`graph-output.txt` simply contains the same ascii graph that was also output +to the terminal. `raw-data.csv` contains the raw benchmarks results which can +be useful for further analyses. diff --git a/tools/runtime-env/main.cpp b/tools/runtime-env/main.cpp new file mode 100644 index 0000000..c8e543b --- /dev/null +++ b/tools/runtime-env/main.cpp @@ -0,0 +1,496 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright (c) 2021 Kohei Yoshida + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + ************************************************************************/ + +#include <mdds/multi_type_vector/soa/block_util.hpp> +#include <mdds/multi_type_vector/aos/block_util.hpp> + +#include <iostream> +#include <iomanip> +#include <vector> +#include <chrono> +#include <map> +#include <sstream> +#include <fstream> +#include <limits> +#include <iterator> + +using mdds::mtv::lu_factor_t; +using std::cerr; +using std::cout; +using std::endl; + +namespace { + +std::string to_string(lu_factor_t lu) +{ + int lu_value = int(lu) & 0xFF; + bool sse2 = (int(lu) & 0x100) != 0; + bool avx2 = (int(lu) & 0x200) != 0; + + std::ostringstream os; + os << (sse2 ? "sse2+" : "") << (avx2 ? "avx2+" : "") << std::setw(2) << std::setfill('0') << lu_value; + + return os.str(); +} + +std::string reflow_text(std::string s, std::size_t width) +{ + // Tokenize the text first. + std::vector<std::string> tokens; + + const char* p = s.data(); + const char* p_end = p + s.size(); + const char* p0 = nullptr; + + for (; p != p_end; ++p) + { + if (!p0) + p0 = p; + + if (*p == ' ' && p0) + { + std::string token(p0, p - p0); + tokens.emplace_back(p0, p - p0); + p0 = nullptr; + } + } + + if (p0) + tokens.emplace_back(p0, p - p0); + + std::vector<std::string> lines(1, std::string()); + + for (const std::string& token : tokens) + { + std::string this_line = lines.back(); // copy + if (this_line.empty()) + this_line = token; + else + this_line += ' ' + token; + + if (this_line.size() > width) + lines.push_back(token); + else + lines.back() = this_line; + } + + std::ostringstream os; + std::copy(lines.begin(), lines.end(), std::ostream_iterator<std::string>(os, "\n")); + return os.str(); +} + +std::string pad_right(std::string s, int width) +{ + int gap = width - int(s.size()); + if (gap < 0) + return s; + + return s + std::string(gap, ' '); +} + +class section_timer +{ +public: + explicit section_timer() + { + m_start_time = get_time(); + } + + double get_duration() const + { + double end_time = get_time(); + return end_time - m_start_time; + } + +private: + double get_time() const + { + unsigned long usec_since_epoch = + std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()) + .count(); + + return usec_since_epoch / 1000000.0; + } + + double m_start_time; +}; + +class data_handler +{ + struct key_type + { + std::string type; + lu_factor_t lu; + + key_type(const std::string& type_, lu_factor_t lu_) : type(type_), lu(lu_) + {} + + bool operator<(const key_type& other) const + { + if (type != other.type) + return type < other.type; + + return lu < other.lu; + } + + std::string to_string() const + { + std::ostringstream os; + os << '(' << type << ", " << ::to_string(lu) << ')'; + return os.str(); + } + }; + + struct duration_type + { + double duration = 0.0; + int count = 0; + + duration_type(double duration_, int count_) : duration(duration_), count(count_) + {} + + std::string to_string() const + { + std::ostringstream os; + os << std::setprecision(4) << duration << '/' << count; + return os.str(); + } + }; + + using records_type = std::map<key_type, duration_type>; + using raw_records_type = std::vector<std::tuple<std::string, lu_factor_t, int, int, double>>; + records_type m_records; + raw_records_type m_raw_records; + int m_insert_count = 0; + + void draw_graph() const + { + if (m_records.empty()) + return; + + // Convert to sequence of average durations. + std::vector<std::tuple<key_type, double>> averages; + averages.reserve(m_records.size()); + + for (const auto& kv : m_records) + { + const duration_type& v = kv.second; + averages.emplace_back(kv.first, v.duration / v.count); + } + + // Sort by durations. + std::sort(averages.begin(), averages.end(), [](const auto& left, const auto& right) -> bool { + return std::get<1>(left) < std::get<1>(right); + }); + + const int n_ticks_max = 55; + + double min_v = std::numeric_limits<double>::max(); + double max_v = std::numeric_limits<double>::min(); + + for (const auto& average : averages) + { + double v = std::get<1>(average); + min_v = std::min(min_v, v); + max_v = std::max(max_v, v); + } + + double tick_width = max_v / n_ticks_max; + + std::vector<std::pair<std::string, std::string>> lines; + lines.reserve(averages.size()); + int max_label_width = 0; + + for (const auto& average : averages) + { + const key_type& k = std::get<0>(average); + double v = std::get<1>(average); + + lines.emplace_back(); + auto& line = lines.back(); + + int n_ticks = v / tick_width; + + // Create and store the label first. + std::ostringstream label; + label << '(' << k.type << ", " << to_string(k.lu) << ')'; + line.first = label.str(); + + char tick = k.type == "SoA" ? 'o' : '+'; + + // Create and store the bar next. + std::ostringstream bar; + bar << std::string(n_ticks, tick) << ' ' << std::setprecision(4) << v; + line.second = bar.str(); + + max_label_width = std::max<int>(max_label_width, line.first.size()); + } + + for (auto& line : lines) + line.first = pad_right(std::move(line.first), max_label_width); + + std::ostringstream graph_out; + + { + // Print the top label and axis. Make sure to rewind to erase the + // progress text. + std::string line = pad_right(" Category", max_label_width); + line += " | Average duration (seconds)"; + graph_out << line << "\n"; + + line = std::string(max_label_width, '-') + "-+-" + std::string(n_ticks_max, '-') + '>'; + graph_out << line << "\n"; + } + + for (const auto& line : lines) + graph_out << line.first << " | " << line.second << "\n"; + + graph_out << "\n"; + + const key_type& top_key = std::get<0>(averages[0]); + std::ostringstream os; + os << "Storage of " << top_key.type << " with the LU factor of " << to_string(top_key.lu) + << " appears to be the best choice in this environment."; + + graph_out << reflow_text(os.str(), 70) << endl; + + std::string graph_out_s = graph_out.str(); + + cout << "\r" << graph_out_s; + + std::ofstream of("graph-output.txt"); + of << graph_out_s << std::flush; + } + + void write_csv() const + { + std::ofstream of("raw-data.csv"); + of << "storage,factor,block count,repeat count,duration\n"; + + for (const auto& rec : m_raw_records) + { + const std::string& type = std::get<0>(rec); + lu_factor_t lu = std::get<1>(rec); + int block_size = std::get<2>(rec); + int repeats = std::get<3>(rec); + double duration = std::get<4>(rec); + + of << type << "," << to_string(lu) << "," << block_size << "," << repeats << "," << duration << "\n"; + } + + of << std::flush; + } + +public: + data_handler() + {} + + void start() + { + m_insert_count = 0; + } + + void end() + { + draw_graph(); + write_csv(); + } + + void record_time(const std::string& type, lu_factor_t lu, int block_size, int repeats, double duration) + { + key_type key(type, lu); + + auto it = m_records.lower_bound(key); + if (it != m_records.end() && !m_records.key_comp()(key, it->first)) + { + // key exists + duration_type& v = it->second; + v.duration += duration; + ++v.count; + } + else + { + // key doesn't yet exist. + m_records.insert(it, records_type::value_type(key, {duration, 1})); + } + + if (!(++m_insert_count & 0x1F)) + { + int n_ticks = m_insert_count >> 5; + cout << "\rprogress: " << std::string(n_ticks, '#') << std::flush; + } + + m_raw_records.emplace_back(type, lu, block_size, repeats, duration); + } +}; + +/** + * Class designed to measure run-time performance of AoS multi_type_vector + * with various loop-unrolling factors. + */ +class mtv_aos_luf_runner +{ + data_handler& m_handler; + + struct block + { + std::size_t position; + std::size_t size; + void* data; + + block(std::size_t _position, std::size_t _size) : position(_position), size(_size) + {} + }; + + using blocks_type = std::vector<block>; + + template<lu_factor_t Factor> + void measure_duration(blocks_type blocks, int block_size, int repeats) + { + using namespace mdds::mtv::aos::detail; + + section_timer st; + for (int i = 0; i < repeats; ++i) + adjust_block_positions<blocks_type, Factor>{}(blocks, 0, 1); + + m_handler.record_time("AoS", Factor, block_size, repeats, st.get_duration()); + } + +public: + mtv_aos_luf_runner(data_handler& dh) : m_handler(dh) + {} + + void run(int block_size, int repeats) + { + blocks_type blocks; + + std::size_t pos = 0; + std::size_t size = 2; + for (int i = 0; i < block_size; ++i) + { + blocks.emplace_back(pos, size); + pos += size; + } + + measure_duration<lu_factor_t::none>(blocks, block_size, repeats); + measure_duration<lu_factor_t::lu4>(blocks, block_size, repeats); + measure_duration<lu_factor_t::lu8>(blocks, block_size, repeats); + measure_duration<lu_factor_t::lu16>(blocks, block_size, repeats); + measure_duration<lu_factor_t::lu32>(blocks, block_size, repeats); + } +}; + +class mtv_soa_luf_runner +{ + data_handler& m_handler; + + struct blocks_type + { + std::vector<std::size_t> positions; + std::vector<std::size_t> sizes; + std::vector<void*> element_blocks; + }; + + template<lu_factor_t Factor> + void measure_duration(blocks_type blocks, int block_size, int repeats) + { + using namespace mdds::mtv::soa::detail; + + section_timer st; + for (int i = 0; i < repeats; ++i) + adjust_block_positions<blocks_type, Factor>{}(blocks, 0, 1); + + m_handler.record_time("SoA", Factor, block_size, repeats, st.get_duration()); + } + +public: + mtv_soa_luf_runner(data_handler& dh) : m_handler(dh) + {} + + void run(int block_size, int repeats) + { + blocks_type blocks; + + std::size_t pos = 0; + std::size_t size = 2; + for (int i = 0; i < block_size; ++i) + { + blocks.positions.push_back(pos); + blocks.sizes.push_back(size); + pos += size; + } + + measure_duration<lu_factor_t::none>(blocks, block_size, repeats); + measure_duration<lu_factor_t::lu4>(blocks, block_size, repeats); + measure_duration<lu_factor_t::lu8>(blocks, block_size, repeats); + measure_duration<lu_factor_t::lu16>(blocks, block_size, repeats); + measure_duration<lu_factor_t::lu32>(blocks, block_size, repeats); +#if SIZEOF_VOID_P == 8 && defined(__SSE2__) + measure_duration<lu_factor_t::sse2_x64>(blocks, block_size, repeats); + measure_duration<lu_factor_t::sse2_x64_lu4>(blocks, block_size, repeats); + measure_duration<lu_factor_t::sse2_x64_lu8>(blocks, block_size, repeats); + measure_duration<lu_factor_t::sse2_x64_lu16>(blocks, block_size, repeats); +#endif +#if SIZEOF_VOID_P == 8 && defined(__AVX2__) + measure_duration<lu_factor_t::avx2_x64>(blocks, block_size, repeats); + measure_duration<lu_factor_t::avx2_x64_lu4>(blocks, block_size, repeats); + measure_duration<lu_factor_t::avx2_x64_lu8>(blocks, block_size, repeats); +#endif + } +}; + +} // namespace + +int main() +{ + int block_count_init = 5; + int block_count_step = 5; + int block_count_max = 300; + int repeats = 1000000; + + data_handler dh; + dh.start(); + + for (int block_count = block_count_init; block_count <= block_count_max; block_count += block_count_step) + { + mtv_aos_luf_runner runner(dh); + runner.run(block_count, repeats); + } + + for (int block_count = block_count_init; block_count <= block_count_max; block_count += block_count_step) + { + mtv_soa_luf_runner runner(dh); + runner.run(block_count, repeats); + } + + dh.end(); + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |