diff --git a/source/SlackBuild/fio/avxjudge.py b/source/SlackBuild/fio/avxjudge.py new file mode 100644 index 00000000..32604ace --- /dev/null +++ b/source/SlackBuild/fio/avxjudge.py @@ -0,0 +1,332 @@ +""" +avxjudge.py is a tool that RPM builds use when building for AVX2 or AVX512 +optimisations. It attempts to heuristically guess whether the library file has +enough AVX instructions to be worth keeping. +""" +#!/usr/bin/python3 +import subprocess +import sys +import re +import argparse +import os + +# MMX and SSE2 instructions +sse_instructions_xmm = set([ + "paddb", "paddd", "paddsb", "paddsw", "paddusb", "psubw", + "paddusw", "paddw", "pmaddwd", "pmulhw", "pmullw", "psubb", "psubsb", + "psubsw", "psubusb", "paddusw", "paddw", "pmaddwd", "pmulhw", "pmullw", + "psubb", "psubd", "psubd", "psubsb", "psubsw", "psubusb", "psubusw" +]) + +# 0.1 value instructions +avx2_instructions_lv = set(["shrx", "rorx", "shlx", "shrx", "shrx", "movbe"]) +avx2_instructions_ymm = set([ + "vpaddq", "vpaddd", "vpsubq", "vpsubd", "vmulpd", "vaddpd", "vsubpd", + "vmulps", "vaddps", "vsubps", "vpmaxsq", "vpminsq", "vpmuludq", + "vpand", "vpmaxud", "vpminud", "vpmaxsd", "vpmaxsw", "vpminsd", + "vpminsw", "vpand", "vpor", "vpmulld" +]) +avx512_instructions_lv = set() + +# 1.0 value instructions +avx2_instructions = set([ + "vfmadd132ss", "vfmadd213ss", "vfmadd231ss", "vfmadd132sd", + "vfmadd231sd", "vfmadd213sd", + "vfmsub132ss", "vfmsub213ss", "vfmsub231ss", "vfmsub132sd", "vfmsub231sd", + "vfmsub213sd", + "vfnmadd132ss", "vfnmadd213ss", "vfnmadd231ss", "vfnmadd132sd", + "vfnmadd231sd", "vfnmadd213sd", + "vfnmsub132ss", "vfnmsub213ss", "vfnmsub231ss", "vfnmsub132sd", + "vfnmsub231sd", "vfnmsub213sd", +]) +avx512_instructions = set() + +# 2.0 value instructions +avx2_instructions_hv = set([ + "vpclmulhqlqdq", "vpclmullqhqdq", + "vfmadd132ps", "vfmadd213ps", "vfmadd231ps", "vfmadd132pd", "vfmadd231pd", + "vfmadd213pd", "vfmsub132ps", "vfmsub213ps", "vfmsub231ps", "vfmsub132pd", + "vfmsub231pd", "vfmsub213pd", + "vfnmadd132ps", "vfnmadd213ps", "vfnmadd231ps", "vfnmadd132pd", + "vfnmadd231pd", "vfnmadd213pd", "vfnmsub132ps", "vfnmsub213ps", + "vfnmsub231ps", "vfnmsub132pd", "vfnmsub231pd", "vfnmsub213pd", "vdivpd", +]) +avx512_instructions_hv = set() + +# Minimum thresholds for keeping libraries +min_count = 10 +min_score = 1.0 + +debug = 0 + +class FunctionRecord(): + def __init__(self): + self.scores = {"sse": 0.0, "avx2": 0.0, "avx512": 0.0} + self.counts = {"sse": 0, "avx2": 0, "avx512": 0} + self.instructions = 0 + self.name = "" + + +class RecordKeeper(): + def __init__(self, delete_type): + self.total_counts = {"sse": 0, "avx2": 0, "avx512": 0} + self.total_scores = {"sse": 0.0, "avx2": 0.0, "avx512": 0.0} + self.functions = {"sse": dict(), "avx2": dict(), "avx512": dict()} + self.ratios = {"sse": dict(), "avx2": dict(), "avx512": dict()} + self.function_record = FunctionRecord() + self.delete_type = delete_type + + def should_delete(self) -> bool: + if self.delete_type and self.total_counts[self.delete_type] < min_count and self.total_scores[self.delete_type] <= min_score: + return True + return False + + def finalize_function_attrs(self): + for i in ("sse", "avx2", "avx512"): + if self.function_record.counts[i] >= 1: + self.functions[i][self.function_record.name] = self.function_record.scores[i] + self.ratios[i][self.function_record.name] = 100.0 * self.function_record.counts[i] / self.function_record.instructions + self.total_scores[i] += self.function_record.scores[i] + self.total_counts[i] += self.function_record.counts[i] + + +def is_sse(instruction:str, args:str) -> float: + + val: float = -1.0 + if "xmm" in args: + if ("pd" in instruction or "ps" in instruction or instruction in sse_instructions_xmm): + val = 1.0 + else: + val = 0.01 + return val + + +def is_avx2(instruction:str, args:str) -> float: + val: float = -1.0 + + if "ymm" in args: + if ("pd" in instruction or "ps" in instruction or instruction in avx2_instructions_ymm) and "xor" not in instruction and "vmov" not in instruction: + val = 1.0 + else: + val = 0.01 + + if instruction in avx2_instructions_lv: + val = max(val, 0.1) + if instruction in avx2_instructions: + val = max(val, 1.0) + if instruction in avx2_instructions_hv: + val = max(val, 2.0) + + return val + +def has_high_register(args: str) -> bool: + return args.endswith(( + 'mm16', 'mm17', 'mm18', 'mm19', 'mm20', 'mm21', 'mm22', + 'mm23', 'mm24', 'mm25', 'mm26', 'mm27', 'mm28', 'mm29', + 'mm30', 'mm31' + )) + +def is_avx512(instruction:str, args:str) -> float: + val: float = -1.0 + + if instruction in avx512_instructions_lv: + val = max(val, 0.1) + if instruction in avx512_instructions: + val = max(val, 1.0) + if instruction in avx512_instructions_hv: + val = max(val, 2.0) + + if "xor" not in instruction and "ymm" in args and has_high_register(args): + val = max(val, 0.02) + if "xor" not in instruction and has_high_register(args): + val = max(val, 0.01) + + if "zmm" in args: + if ("pd" in instruction or "ps" in instruction or "vpadd" in instruction or "vpsub" in instruction or instruction in avx2_instructions_ymm) and "xor" not in instruction and "vmov" not in instruction: + val = max(val, 1.0) + else: + val = max(val, 0.01) + + + return val + + +def ratio(f: float) -> str: + f = f * 100 + f = round(f)/100.0 + return str(f) + +def print_top_functions(records:RecordKeeper) -> None: + def summarize(table: dict, is_pct: bool, max_funcs: int = 5) -> None: + for f in sorted(table, key=table.get, reverse=True)[:max_funcs]: + f = " %-30s\t%s" % (f, ratio(table[f])) + + if is_pct: + print(f, "%s") + else: + print(f) + + sets = ( + ("SSE", records.functions["sse"], records.ratios["sse"]), + ("AVX2", records.functions["avx2"], records.ratios["avx2"]), + ("AVX512", records.functions["avx512"], records.ratios["avx512"]), + ) + + for set_name, funcs, funcs_ratio in sets: + print("Top %s functions by instruction count" % set_name) + summarize(funcs_ratio, True) + print() + + print("Top %s functions by value" % set_name) + summarize(funcs, False) + print() + +sse_avx2_duplicate_cnt = 0 +avx2_avx512_duplicate_cnt = 0 + +def process_objdump_line(records:RecordKeeper, line:str, verbose:int, quiet:int) -> None: + sse_score = -1.0 + avx2_score = -1.0 + avx512_score = -1.0 + sse_str = " " + avx2_str = " " + avx512_str = "" + + global sse_avx2_duplicate_cnt + global avx2_avx512_duplicate_cnt + global debug + + match = re.search("^(.*)\#.*", line) + if match: + line = match.group(1) + + match = re.search(".*[0-9a-f]+\:\t[0-9a-f\ ]+\t([a-zA-Z0-9]+) (.*)", line) + if match: + ins = match.group(1) + arg = match.group(2) + + avx512_score = is_avx512(ins, arg) + if avx512_score <= 0: + avx2_score = is_avx2(ins, arg) + if avx2_score <= 0 and avx512_score <= 0: + sse_score = is_sse(ins, arg) + + records.function_record.instructions += 1 + + match = re.search("\<([a-zA-Z0-9_@\.\-]+)\>\:", line) + if match: + records.function_record.name = match.group(1) + if records.function_record.instructions > 0 and verbose > 0: + print(records.function_record.name, + "\t", ratio(records.function_record.counts["sse"] / records.function_record.instructions), + "\t", ratio(records.function_record.counts["avx2"] / records.function_record.instructions), + "\t", ratio(records.function_record.counts["avx512"] / records.function_record.instructions), + "\t", records.function_record.scores["sse"], + "\t", records.function_record.scores["avx2"], + "\t", records.function_record.scores["avx512"]) + if records.function_record.instructions > 0: + records.finalize_function_attrs() + records.function_record = FunctionRecord() + + if sse_score >= 0.0: + sse_str = str(sse_score) + records.function_record.scores["sse"] += sse_score + records.function_record.counts["sse"] += 1 + + if avx2_score >= 0.0: + avx2_str = str(avx2_score) + records.function_record.scores["avx2"] += avx2_score + records.function_record.counts["avx2"] += 1 + + if avx512_score >= 0.0: + avx512_str = str(avx512_score) + records.function_record.scores["avx512"] += avx512_score + records.function_record.counts["avx512"] += 1 + + if sse_score >=0.0 and avx2_score >= 0.0 and debug: + sse_avx2_duplicate_cnt +=1 + print("duplicate count for sse & avx2 ?", ins, arg, sse_avx2_duplicate_cnt) + + if avx512_score >= 0.0 and avx2_score >= 0.0 and debug: + avx2_avx512_duplicate_cnt +=1 + print("duplicate count for avx2 & avx512 ?", ins, arg, avx2_avx512_duplicate_cnt) + + if not records.should_delete() and quiet != 0: + sys.exit(0) + + if verbose > 0: + print(sse_str,"\t",avx2_str,"\t", avx512_str,"\t", line) + + +def do_file(filename: str, verbose:int, quiet:int, delete_type:str) -> None: + global debug + + records = RecordKeeper(delete_type) + + if quiet == 0: + print("Analyzing", filename) + + p = subprocess.Popen(["objdump","-d", filename], stdout=subprocess.PIPE) + for line in p.stdout: + process_objdump_line(records, line.decode("latin-1"), verbose, quiet) + output, _ = p.communicate() + for line in output.decode("latin-1").splitlines(): + process_objdump_line(records, line, verbose, quiet) + if quiet <= 0: + print_top_functions(records) + print() + print("File total (SSE): ", records.total_counts["sse"],"instructions with score", round(records.total_scores["sse"])) + print("File total (AVX2): ", records.total_counts["avx2"],"instructions with score", round(records.total_scores["avx2"])) + print("File total (AVX512): ", records.total_counts["avx512"],"instructions with score", round(records.total_scores["avx512"])) + print() + if debug: + print("File duplicate count of sse&avx2", sse_avx2_duplicate_cnt, ", duplicate count of avx2&avx512", avx2_avx512_duplicate_cnt) + + if records.should_delete(): + print(filename, "\t", delete_type, "count:", records.total_counts[delete_type],"\t", delete_type, "value:", ratio(records.total_scores[delete_type])) + try: + os.unlink(filename) + except: + None + + +def main(): + global debug + + verbose = 0 + quiet = 0 + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true") + parser.add_argument("-q", "--quiet", help="decrease output verbosity", action="store_true") + parser.add_argument("-d", "--debug", help="print out more debug info", action="store_true") + parser.add_argument("filename", help = "The filename to inspect") + group = parser.add_mutually_exclusive_group() + group.add_argument("-1", "--unlinksse", help="unlink the file if it has no SSE instructions", action="store_true") + group.add_argument("-2", "--unlinkavx2", help="unlink the file if it has no AVX2 instructions", action="store_true") + group.add_argument("-5", "--unlinkavx512", help="unlink the file if it has no AVX512 instructions", action="store_true") + + args = parser.parse_args() + if args.verbose: + verbose = 1 + + if args.quiet: + verbose = 0 + quiet = 1 + + if args.debug: + debug = 1 + + if args.unlinksse: + deltype = "sse" + elif args.unlinkavx2: + deltype = "avx2" + elif args.unlinkavx512: + deltype = "avx512" + else: + deltype = "" + + do_file(args.filename, verbose, quiet, deltype) + + +if __name__ == '__main__': + main() diff --git a/source/SlackBuild/fio/doinst.sh b/source/SlackBuild/fio/doinst.sh new file mode 100644 index 00000000..5fb28930 --- /dev/null +++ b/source/SlackBuild/fio/doinst.sh @@ -0,0 +1,3 @@ +if [ -x /usr/bin/update-desktop-database ]; then + /usr/bin/update-desktop-database -q usr/share/applications >/dev/null 2>&1 +fi diff --git a/source/SlackBuild/fio/fio-3.15.tar.gz b/source/SlackBuild/fio/fio-3.15.tar.gz new file mode 100644 index 00000000..07acdb74 Binary files /dev/null and b/source/SlackBuild/fio/fio-3.15.tar.gz differ diff --git a/source/SlackBuild/fio/fio-3.23.tar.gz b/source/SlackBuild/fio/fio-3.23.tar.gz new file mode 100644 index 00000000..6b36ac30 Binary files /dev/null and b/source/SlackBuild/fio/fio-3.23.tar.gz differ diff --git a/source/SlackBuild/fio/fio.SlackBuild b/source/SlackBuild/fio/fio.SlackBuild new file mode 100644 index 00000000..b59b97f9 --- /dev/null +++ b/source/SlackBuild/fio/fio.SlackBuild @@ -0,0 +1,108 @@ +#!/bin/sh + +# Slackware build script for fio + +# Copyright 2012 Binh Nguyen +# Copyright 2015-2019 Brenton Earl +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +PRGNAM=fio +VERSION=${VERSION:-3.23} +BUILD=${BUILD:-1} +TAG=${TAG:-_SBo} + +if [ -z "$ARCH" ]; then + case "$( uname -m )" in + i?86) ARCH=i586 ;; + arm*) ARCH=arm ;; + *) ARCH=$( uname -m ) ;; + esac +fi + +CWD=$(pwd) +TMP=${TMP:-/tmp/SBo} +PKG=$TMP/package-$PRGNAM +OUTPUT=${OUTPUT:-/tmp} + +if [ "$ARCH" = "i586" ]; then + SLKCFLAGS="-O2 -march=i586 -mtune=i686" + LIBDIRSUFFIX="" +elif [ "$ARCH" = "i686" ]; then + SLKCFLAGS="-O2 -march=i686 -mtune=i686" + LIBDIRSUFFIX="" +elif [ "$ARCH" = "x86_64" ]; then + SLKCFLAGS="-O2 -fPIC" + LIBDIRSUFFIX="64" +else + SLKCFLAGS="-O2" + LIBDIRSUFFIX="" +fi + +# Fio has a Gtk interface that is not built by default. +# To enable it pass 'yes' to the GUI variable +# Example: GUI=yes sh fio.SlackBuild +gui="" ; [ "$GUI" = "yes" ] && gui="--enable-gfio" + +set -e + +rm -rf $PKG +mkdir -p $TMP $PKG $OUTPUT +cd $TMP +rm -rf $PRGNAM-$VERSION +tar xvf $CWD/$PRGNAM-$VERSION.tar.gz +cd $PRGNAM-$VERSION +chown -R root:root . +find -L . \ + \( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \ + -o -perm 511 \) -exec chmod 755 {} \; -o \ + \( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \ + -o -perm 440 -o -perm 400 \) -exec chmod 644 {} \; + +./configure \ + --prefix="/usr" \ + --extra-cflags="$SLKCFLAGS" \ + $gui + +make +make install DESTDIR=$PKG + +find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \ + | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true + +find $PKG/usr/man -type f -exec gzip -9 {} \; +for i in $( find $PKG/usr/man -type l ) ; do ln -s $( readlink $i ).gz $i.gz ; rm $i ; done + +mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION +cp -a COPYING HOWTO README REPORTING-BUGS examples/ $PKG/usr/doc/$PRGNAM-$VERSION +cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild + +# Add .desktop file if GUI is built +# No icon available +if [ "$GUI" = "yes" ]; then + mkdir -p $PKG/usr/share/applications + cat $CWD/$PRGNAM.desktop > $PKG/usr/share/applications/$PRGNAM.desktop +fi + +mkdir -p $PKG/install +cat $CWD/doinst.sh > $PKG/install/doinst.sh +cat $CWD/slack-desc > $PKG/install/slack-desc + +cd $PKG +/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.${PKGTYPE:-txz} diff --git a/source/SlackBuild/fio/fio.desktop b/source/SlackBuild/fio/fio.desktop new file mode 100644 index 00000000..190d6f2b --- /dev/null +++ b/source/SlackBuild/fio/fio.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Gfio +GenericName=Flexible I/O tester front-end +Type=Application +Exec=gfio +Icon=applications-utilities +Categories=System; +Terminal=false +StartupNotify=false diff --git a/source/SlackBuild/fio/fio.info b/source/SlackBuild/fio/fio.info new file mode 100644 index 00000000..68043450 --- /dev/null +++ b/source/SlackBuild/fio/fio.info @@ -0,0 +1,10 @@ +PRGNAM="fio" +VERSION="3.14" +HOMEPAGE="http://git.kernel.dk/cgit/fio/" +DOWNLOAD="http://brick.kernel.dk/snaps/fio-3.14.tar.gz" +MD5SUM="54eabdbcaac1d0d1edcd8a3bb6c927fc" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +REQUIRES="" +MAINTAINER="Brenton Earl" +EMAIL="brent@exitstatusone.com" diff --git a/source/SlackBuild/fio/fio.tar.gz b/source/SlackBuild/fio/fio.tar.gz new file mode 100644 index 00000000..6bca5175 Binary files /dev/null and b/source/SlackBuild/fio/fio.tar.gz differ diff --git a/source/SlackBuild/fio/libaio-0.3.112-x86_64-1.txz b/source/SlackBuild/fio/libaio-0.3.112-x86_64-1.txz new file mode 100644 index 00000000..92c008e7 Binary files /dev/null and b/source/SlackBuild/fio/libaio-0.3.112-x86_64-1.txz differ diff --git a/source/SlackBuild/fio/slack-desc b/source/SlackBuild/fio/slack-desc new file mode 100644 index 00000000..259f5d67 --- /dev/null +++ b/source/SlackBuild/fio/slack-desc @@ -0,0 +1,19 @@ +# HOW TO EDIT THIS FILE: +# The "handy ruler" below makes it easier to edit a package description. +# Line up the first '|' above the ':' following the base package name, and +# the '|' on the right side marks the last column you can put a character in. +# You must make exactly 11 lines for the formatting to be correct. It's also +# customary to leave one space after the ':' except on otherwise blank lines. + + |-----handy-ruler------------------------------------------------------| +fio: fio (Flexible I/O Tester) +fio: +fio: fio is a tool that will spawn a number of threads or processes doing +fio: a particular type of io action as specified by the user. fio takes a +fio: number of global parameters, each inherited by the thread unless +fio: otherwise parameters given to them overriding that setting is given. +fio: The typical use of fio is to write a job file matching the io load +fio: one wants to simulate. +fio: +fio: Homepage: http://git.kernel.dk/cgit/fio/ +fio: