public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
* [PATCH v2] passt, pasta: Run-time selection of AVX2 build
@ 2022-02-28 15:48 Stefano Brivio
  0 siblings, 0 replies; only message in thread
From: Stefano Brivio @ 2022-02-28 15:48 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 10559 bytes --]

Build-time selection of AVX2 flags and routines is not practical for
distributions, but limiting AVX2 usage to checksum routines with
specific run-time detection doesn't allow for easy performance gains
from auto-vectorisation of batched packet handling routines.

For x86_64, build non-AVX2 and AVX2 binaries, and implement a simple
wrapper replacing the current executable with the AVX2 build if it's
available, and if AVX2 is supported by the current CPU.

Signed-off-by: Stefano Brivio <sbrivio(a)redhat.com>
---
v2: Add arch.c and arch.h to commit

 Makefile        | 38 ++++++++++++++++++++++++++++----------
 README.md       | 28 +++++++++++-----------------
 arch.c          | 42 ++++++++++++++++++++++++++++++++++++++++++
 arch.h          |  6 ++++++
 hooks/pre-push  |  9 ---------
 passt.c         |  3 +++
 test/build/all  | 10 ----------
 test/demo/passt |  2 +-
 test/demo/pasta |  2 +-
 9 files changed, 92 insertions(+), 48 deletions(-)
 create mode 100644 arch.c
 create mode 100644 arch.h

diff --git a/Makefile b/Makefile
index 031b684..8387719 100644
--- a/Makefile
+++ b/Makefile
@@ -14,8 +14,11 @@ ifeq ($(RLIMIT_STACK_VAL),unlimited)
 RLIMIT_STACK_VAL := 1024
 endif
 
-AUDIT_ARCH := $(shell uname -m | tr [a-z] [A-Z])
-AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/^ARM.*/ARM/')
+# Get 'uname -m'-like architecture description for target
+TARGET_ARCH := $(shell $(CC) -dumpmachine | cut -f1 -d- | tr [a-z] [A-Z])
+TARGET_ARCH := $(shell echo $(TARGET_ARCH) | sed 's/POWERPC/PPC/')
+
+AUDIT_ARCH := $(shell echo $(TARGET_ARCH) | sed 's/^ARM.*/ARM/')
 AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/I[456]86/I386/')
 AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/PPC64/PPC/')
 AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/PPCLE/PPC64LE/')
@@ -25,7 +28,7 @@ CFLAGS += -DPAGE_SIZE=$(shell getconf PAGE_SIZE)
 CFLAGS += -DNETNS_RUN_DIR=\"/run/netns\"
 CFLAGS += -DPASST_AUDIT_ARCH=AUDIT_ARCH_$(AUDIT_ARCH)
 CFLAGS += -DRLIMIT_STACK_VAL=$(RLIMIT_STACK_VAL)
-CFLAGS += -DARCH=\"$(shell uname -m)\"
+CFLAGS += -DARCH=\"$(TARGET_ARCH)\"
 
 # On gcc 11.2, with -O2 and -flto, tcp_hash() and siphash_20b(), if inlined,
 # seem to be hitting something similar to:
@@ -63,10 +66,13 @@ endif
 
 prefix ?= /usr/local
 
+ifeq ($(TARGET_ARCH),X86_64)
+all: passt passt.avx2 pasta pasta.avx2 qrap
+BIN := passt passt.avx2 pasta pasta.avx2 qrap
+else
 all: passt pasta qrap
-
-avx2: CFLAGS += -Ofast -mavx2 -ftree-vectorize -funroll-loops
-avx2: clean all
+BIN := passt pasta qrap
+endif
 
 static: CFLAGS += -static -DGLIBC_NO_STATIC_NSS
 static: clean all
@@ -78,6 +84,16 @@ passt: $(filter-out qrap.c,$(wildcard *.c)) \
 	$(filter-out qrap.h,$(wildcard *.h)) seccomp.h
 	$(CC) $(CFLAGS) $(filter-out qrap.c,$(wildcard *.c)) -o passt
 
+passt.avx2: CFLAGS += -Ofast -mavx2 -ftree-vectorize -funroll-loops
+passt.avx2: $(filter-out qrap.c,$(wildcard *.c)) \
+	$(filter-out qrap.h,$(wildcard *.h)) seccomp.h
+	$(CC) $(CFLAGS) $(filter-out qrap.c,$(wildcard *.c)) -o passt.avx2
+
+passt.avx2: passt
+
+pasta.avx2: passt.avx2
+	ln -s passt.avx2 pasta.avx2
+
 pasta: passt
 	ln -s passt pasta
 	ln -s passt.1 pasta.1
@@ -88,24 +104,26 @@ qrap: qrap.c passt.h
 
 .PHONY: clean
 clean:
-	-${RM} passt *.o seccomp.h qrap pasta pasta.1 \
+	-${RM} passt passt.avx2 *.o seccomp.h qrap pasta pasta.avx2 pasta.1 \
 		passt.tar passt.tar.gz *.deb *.rpm
 
-install: passt pasta qrap
+install: $(BIN)
 	mkdir -p $(DESTDIR)$(prefix)/bin $(DESTDIR)$(prefix)/share/man/man1
-	cp -d passt pasta qrap $(DESTDIR)$(prefix)/bin
+	cp -d $(BIN) $(DESTDIR)$(prefix)/bin
 	cp -d passt.1 pasta.1 qrap.1 $(DESTDIR)$(prefix)/share/man/man1
 
 uninstall:
 	-${RM} $(DESTDIR)$(prefix)/bin/passt
+	-${RM} $(DESTDIR)$(prefix)/bin/passt.avx2
 	-${RM} $(DESTDIR)$(prefix)/bin/pasta
+	-${RM} $(DESTDIR)$(prefix)/bin/pasta.avx2
 	-${RM} $(DESTDIR)$(prefix)/bin/qrap
 	-${RM} $(DESTDIR)$(prefix)/share/man/man1/passt.1
 	-${RM} $(DESTDIR)$(prefix)/share/man/man1/pasta.1
 	-${RM} $(DESTDIR)$(prefix)/share/man/man1/qrap.1
 
 pkgs:
-	tar cf passt.tar -P --xform 's//\/usr\/bin\//' passt pasta qrap
+	tar cf passt.tar -P --xform 's//\/usr\/bin\//' $(BIN)
 	tar rf passt.tar -P --xform 's//\/usr\/share\/man\/man1\//' \
 		passt.1 pasta.1 qrap.1
 	gzip passt.tar
diff --git a/README.md b/README.md
index 14e1777..4966e15 100644
--- a/README.md
+++ b/README.md
@@ -220,7 +220,7 @@ speeding up local connections, and usually requiring NAT. _pasta_:
 * Linux
     * ✅ starting from 4.18 kernel version
     * ✅ starting from 3.13 kernel version
-* 🛠 build-time selection of AVX2 instructions (as much as possible)
+* ✅ run-time selection of AVX2 build
 * ⌚ [_musl_](https://bugs.passt.top/show_bug.cgi?id=4) and
   [_uClibc-ng_](https://bugs.passt.top/show_bug.cgi?id=5)
 * ⌚ [FreeBSD](https://bugs.passt.top/show_bug.cgi?id=6),
@@ -467,15 +467,12 @@ Test logs [here](/builds/latest/test/).
         cd passt
         make
 
-    * alternatively, static builds for x86_64, with or without AVX2 instructions,
-      as of the latest commit are also available for convenience
-      [here](/builds/latest/x86_64/avx2/) and
-      [here](/builds/latest/x86_64/). Convenience, non-official
-      packages for Debian (and derivatives) and RPM-based distributions are also
-      available there. These binaries and packages are simply built with:
+    * alternatively, static builds for x86_64 as of the latest commit are also
+      available for convenience [here](/builds/latest/x86_64/). Convenience,
+      non-official packages for Debian (and derivatives) and RPM-based
+      distributions are also available there. These binaries and packages are
+      simply built with:
 
-            CFLAGS="-static" make avx2
-            make pkgs
             make static
             make pkgs
 
@@ -530,15 +527,12 @@ Test logs [here](/builds/latest/test/).
         cd passt
         make
 
-    * alternatively, static builds for x86_64, with or without AVX2 instructions,
-      as of the latest commit are also available for convenience
-      [here](/builds/latest/x86_64/avx2/) and
-      [here](/builds/latest/x86_64/). Convenience, non-official
-      packages for Debian (and derivatives) and RPM-based distributions are also
-      available there. These binaries and packages are simply built with:
+    * alternatively, static builds for x86_64 as of the latest commit are also
+      available for convenience [here](/builds/latest/x86_64/). Convenience,
+      non-official packages for Debian (and derivatives) and RPM-based
+      distributions are also available there. These binaries and packages are
+      simply built with:
 
-            CFLAGS="-static" make avx2
-            make pkgs
             make static
             make pkgs
 
diff --git a/arch.c b/arch.c
new file mode 100644
index 0000000..b8e1db5
--- /dev/null
+++ b/arch.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+/* PASST - Plug A Simple Socket Transport
+ *  for qemu/UNIX domain socket mode
+ *
+ * PASTA - Pack A Subtle Tap Abstraction
+ *  for network namespace/tap device mode
+ *
+ * arch.c - Architecture-specific implementations
+ *
+ * Copyright (c) 2022 Red Hat GmbH
+ * Author: Stefano Brivio <sbrivio(a)redhat.com>
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/**
+ * arch_avx2_exec() - Run AVX2 build if supported, drop suffix from argv[0]
+ * @argv:	Arguments from command line
+ */
+#ifdef __x86_64__
+void arch_avx2_exec(char **argv)
+{
+	char *p = strstr(argv[0], ".avx2");
+
+	if (p) {
+		*p = 0;
+	} else if (__builtin_cpu_supports("avx2")) {
+		char path[PATH_MAX];
+
+		snprintf(path, PATH_MAX, "%s.avx2", argv[0]);
+		argv[0] = path;
+		execve(path, argv, environ);
+		perror("Can't run AVX2 build, using non-AVX2 version");
+	}
+}
+#else
+void arch_avx2_exec(char **argv) { (void)argv; }
+#endif
diff --git a/arch.h b/arch.h
new file mode 100644
index 0000000..ce1c01b
--- /dev/null
+++ b/arch.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: AGPL-3.0-or-later
+ * Copyright (c) 2022 Red Hat GmbH
+ * Author: Stefano Brivio <sbrivio(a)redhat.com>
+ */
+
+void arch_avx2_exec(char **argv);
diff --git a/hooks/pre-push b/hooks/pre-push
index a3f67f4..6a9b712 100755
--- a/hooks/pre-push
+++ b/hooks/pre-push
@@ -58,15 +58,6 @@ ssh "${USER_HOST}" 				"rm -f ${BIN}/*.deb"
 ssh "${USER_HOST}"				"rm -f ${BIN}/*.rpm"
 scp *.deb *.rpm					"${USER_HOST}:${BIN}/"
 
-CFLAGS="-static -DGLIBC_NO_STATIC_NSS" make avx2
-ssh "${USER_HOST}"				"mkdir -p ${BIN}/avx2"
-scp passt pasta qrap passt.1 pasta.1 qrap.1	"${USER_HOST}:${BIN}/avx2/"
-
-make pkgs
-ssh "${USER_HOST}"				"rm -f ${BIN}/avx2/*.deb"
-ssh "${USER_HOST}"				"rm -f ${BIN}/avx2/*.rpm"
-scp *.deb *.rpm					"${USER_HOST}:${BIN}/avx2/"
-
 ssh "${USER_HOST}"				"mv ${LATEST} ${AWAY}"
 ssh "${USER_HOST}"				"mv ${TEMP} ${LATEST}"
 ssh "${USER_HOST}"				"rm -rf ${AWAY}"
diff --git a/passt.c b/passt.c
index e7dd108..40d3e57 100644
--- a/passt.c
+++ b/passt.c
@@ -69,6 +69,7 @@
 #include "tap.h"
 #include "conf.h"
 #include "pasta.h"
+#include "arch.h"
 
 #define EPOLL_EVENTS		8
 
@@ -313,6 +314,8 @@ int main(int argc, char **argv)
 	struct sigaction sa;
 	char *log_name;
 
+	arch_avx2_exec(argv);
+
 	check_root();
 	drop_caps();
 
diff --git a/test/build/all b/test/build/all
index 9aa6c61..6043793 100644
--- a/test/build/all
+++ b/test/build/all
@@ -40,13 +40,3 @@ host	CFLAGS="-Werror" make
 check	[ -f passt ]
 check	[ -h pasta ]
 check	[ -f qrap ]
-
-test	Build AVX2
-host	make clean
-check	! [ -e passt ]
-check	! [ -e pasta ]
-check	! [ -e qrap ]
-host	CFLAGS="-Werror" make avx2
-check	[ -f passt ]
-check	[ -h pasta ]
-check	[ -f qrap ]
diff --git a/test/demo/passt b/test/demo/passt
index 76aac86..8838363 100644
--- a/test/demo/passt
+++ b/test/demo/passt
@@ -29,7 +29,7 @@ sleep	1
 say	 and build it.
 sleep	1
 host	cd passt
-host	make avx2
+host	make
 sleep	1
 
 nl
diff --git a/test/demo/pasta b/test/demo/pasta
index b2dd327..74fca85 100644
--- a/test/demo/pasta
+++ b/test/demo/pasta
@@ -169,7 +169,7 @@ say	  more in the "Performance" section below.
 sleep	3
 ns	exit
 passt	exit
-passt	CFLAGS="-g" make avx2
+passt	CFLAGS="-g" make
 sleep	2
 passtb	perf record -g ./pasta
 sleep	2
-- 
@@ -169,7 +169,7 @@ say	  more in the "Performance" section below.
 sleep	3
 ns	exit
 passt	exit
-passt	CFLAGS="-g" make avx2
+passt	CFLAGS="-g" make
 sleep	2
 passtb	perf record -g ./pasta
 sleep	2
-- 
2.34.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2022-02-28 15:48 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-28 15:48 [PATCH v2] passt, pasta: Run-time selection of AVX2 build Stefano Brivio

Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).