Splitting up work to be split across mutiple slots on the same gpu for higher total tokens per second

ok so i am trying to increase performance of llms i have running on my 7900 xtx via hipfire, i notice i get significantly higher total tokens per second when i run mutiple slots at once when running qwen 3.8 27b.

i am running into 2 road blocks tho, 1 context each slot gets a progressively smaller context as increase the number of slots. is there a good way to do more with the same given total amount of vram, i assume there is going to be a large amount of overlap for stuff like system prompts, tho i use a relatively minimal system prompt that links to files so if a model only actually reads system prompts realvent to it’s own task which makes it harder to just say this text gets put into a shared context, i also image if i have them working on similar tasks there will be a large amount of overlap.

2 alot of tasks aren’t easy to split up into mutiple smaller tasks that can be done in parrel without proper knowledge of previous and future steps, maybe something like a shared context or a messaging board would work well?

also a more experimental idea to further speed up general prompts is to instead have all my prompts processed by a “orchestration” slot which splits up a given prompt into X number of tasks then gives these to new prompts to different slots and then the “orchestration” slot dies to free up more vram for context, i could also route something like this threw a decision model like kev to determine if a given task would work well being split up.

Do you mean Tensor Parallelism or something else?

no i mean mutiple slots on one gpu ie 2 conversations 1 set of model weights 1 gpu.

You can likely host a couple of chats at once in that. More users will slow it down, tho.

no this is all for 1 user me, i acutely notice a dramatic increase in performance when i run mutiple slots at once.

Can you clarify what you mean by slots? Most of us are probably interpreting slots to mean physical pcie slots, but it sounds like you mean something else.

each slot is kind of a instance of a “chat” running off the same weights, so i can have qwen 27b loaded on 1 card and 2 “chats” running at the same time off those same weights, they can either have 1 shared context or each within own. i saw roughly a a 30% increase in tokens per second when i ran 2 slots simultaneously and another 30 when i ran 4.

Gotcha. You can easily do that. If you’re using something like Open WebUI you can just open a second instance of it and interact at the same time. Just rember that tokens/sec doesn’t always equal more productive. The card can crank out lots of individual chats at once, but the more you add the slower each one will feel after a certain point.

yeah thats why i posted this as i am trying to figure out how to best leverage this, i find if i give each slot a similar task and shared context i can easily run 4 at once, and also i am kinda making this around my own custom harnes built around pi so the software stuff i can deal with

Good observation, what you discover is similar to hyper threading : leveraging tiny down time of the CPU to juice out every bit of power creating a continuous flow of tasks.

But on top of that, LLM workload is split in two really different task : one is compute bound and the other is famously memory bound one.
This mean that when you are generating your answer you could have use compute to decode the next question.

In the end what you are asking is what agentic AI is doing, this what is agent in essence : parallelize a given generic problem.
Switching to that would prevent you to reinvente the wheel. :wink:

Yep, this holds true on the Splash engine on macOS (and probably other engines too). For my MacBook Pro (M5 Pro 15C/16C 48GB RAM), highest total throughput is 4, then 2, then 1 concurrent session(s). Though the tok/s for each individual session gets slower the more there are.

As to how useful that observation is… if you were running sub-agents with the goal of completing the whole chunk of work as fast as possible, I guess it would technically be fastest that way? I tend to use 1-2 sub-agents at most (and usually 2 different models on different machines so they’re each as fast as they can be for a single stream) so making each lane slower in order to produce a higher total throughput just isn’t worth it for me.

Figure out a good bench set based on work you actually do/want to do (LLMs will be good at writing scripts to run these, and larger models can produce examples of tricky bugs that small models will struggle with). For testing this you’d need to make it a single goal with multiple steps that can be done concurrently, then you can see if it’s actually faster to run them sequentially (one session/fix at a time) or concurrently. That’d decide if this juice is worth the squeeze at all.

Though it also opens you up to other variables to think about/test, which can get annoying. A higher-bit quant may run slower, but produce a better result, so it burns less time fixing its own mistakes, making it practically faster. Or it could be faster, actually (I had this on my Mac, a flat 4-bit runs faster than 3-bit, it’s something with the way it does the conversion math that makes 3-bit slower to compute). And then you’ve got to consider whether your temp settings are affecting the model’s reasoning capabilities (making it too dull, or too verbose and leading to loops that burn a ton of tokens), as that’ll effect time to completion.

any suggestions on how i could automatically have a llm parllise a given task? ie convert my linear steps of intuitions that are nice and easy to give and split it up into X amount of tasks that can happen in parcel. i could either use a temporary instance of the chosen model for this or i could have my always running qwen 9b (base) run it. (it;s awlays running as i have a kev lora for model routing on a secondary gpu)

yeah good suggestion i have already been kinda doing those kinds of benchmarks, i’m running Gentoo linux and i’ve been trying to debolt my system by remove X11 and 32 bit libraries where possible which makes a pretty good antigenic benchmark. the issue with higher bit quants on a 24 gib card that serious cuts context and amount of slots i can run at once, right now i can get 4 to run pretty easily and find that a single merged context for them gives the best results. r

right now my goto model is 4 bit hipfire quant of qwen 3.8 27b. also experimenting with larger models like nemotron bolt, glm 4.6 air and running most of the weights on the cpu (96 gib of ram) and they keep preforming dramatically worsen then qwen 27b.

my current emerge list of errors c2@gentoobtw ~ $ emerge -pvuDN @worldPassword: --- Invalid atom in /etc/port - Pastebin.com

1 Like

What’s your make.conf look like? Path is /etc/portage/make.conf. And do you remember what profile you chose when installing? IIRC moving to a no-multilib profile is a nightmare, they say in the installation guide to pick multilib or no-multilib and stick with that, as it’s nearly impossible to switch from multilib → no-multilib.

yep thats why it’s a good benchmark. i really only need 32 bit libraries for steam.

c2@gentoobtw ~ $ cat /etc/portage/make.conf
# These settings were set by the catalyst build script that automatically
# built this stage.
# Please consult /usr/share/portage/config/make.conf.example for a more
# detailed example.

#COMMON_FLAGS="-march=native -O3 -pipe -flto=auto -Werror=odr -Werror=lto-type-mismatch -Werror=strict-aliasing -fno-semantic-interposition"
COMMON_FLAGS="-march=native -O3 -pipe -flto=auto -fno-semantic-interposition"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
ACCEPT_LICENSE="*"
#RUSTFLAGS="-C opt-level=3"
 
LC_MESSAGES=C.utf8
MAKEOPTS="-j32 -l32"
MAKEFLAGS="--jobserver-auth=fifo:/dev/steve"
EMERGE_DEFAULT_OPTS="--jobs 32 --load-average=32 --merge-wait-scope=system"
NINJAOPTS="-l32"

VIDEO_CARDS=" amdgpu radeonsi"	
AMDGPU_TARGETS="gfx1100 gfx1030 gfx1032"

ABI_X86="64"


USE="dist-kernel initramfs udisks encode lm-sensors  qt6 vaapi -discord vulkan wayland alsa pipewire systemd aom dav1d svt-av1 vpx x264 x265 fdk-aac libmp3lame libvorbis libopus ffmpeg -gtk -gnome  qt mpv -vlc aac faad fdk mp4 -openrc systemd-boot rocm -cuda openmp hip colord hdr amr amrenc lame openmpt flac speex zimg shaderc snappy jack opencl vdpau drm epub amdgpu bluetooth abi_x86_32 opencl webengine screencast system-ffmpeg lto pgo amf avif blas networkmanager pulseaudio semantic-desktop rdna3 rdna2 -qt5 qt6 numpy torch -dvd -mpeg -jack pulseaudio o3 llvm -x -X -xv -opengl bluetooth -abi_x86_32"
CPU_FLAGS_X86="aes avx avx2 avx512_bf16 avx512_bitalg avx512_vbmi2 avx512_vnni avx512_vp2intersect avx512_vpopcntdq avx512bw avx512cd avx512dq avx512f avx512ifma avx512vbmi avx512vl avx_vnni bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sha sse sse2 sse3 sse4_1 sse4_2 sse4a ssse3 vpclmulqdq"

L10N="en en-US ja"

FEATURES="parallel-fetch parallel-install  binpkg-logs ccache jobserver-token -merge-wait"
CCACHE_SIZE="1024G"
CCACHE_DIR="/var/cache/ccache"


#CCACHE_DIR="/run/media/pciessd/ccach"
#CCACHE_SIZE="300G"
#DISTDIR=/run/media/nvme2/distfiles
#PORTAGE_TMPDIR="/run/media/nvme2/tmp"
PORTDIR_OVERLAY="/usr/local/portage/overlay"
LLVM_TARGETS="X86 AMDGPU"
#CPU_FLAGS_X86 = aes avx avx2 avx512_bf16 avx512_bitalg avx512_vbmi2 avx512_vnni avx512_vp2intersect avx512_vpopcntdq avx512bw avx512cd avx512dq avx512f avx512ifma avx512vbmi avx512vl avx_vnni bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sha sse sse2 sse3 sse4_1 sse4_2 sse4a ssse3 vpclmulqdq
CARGO_BUILD_JOBS="32" 
PYTHON_COMPILE_JOBS="32"

LDFLAGS="${LDFLAGS} -fuse-ld=mold -flto=auto"

#LDFLAGS="-fuse-ld=lld -Wl,--threads=32" 

ADAFLAGS=${COMMON_FLAGS}
DFLAGS=${COMMON_FLAGS}
OBJCFLAGS=${COMMON_FLAGS}
OBJCXXFLAGS=${COMMON_FLAGS}
RUSTFLAGS="-C target-cpu=native -C opt-level=3"
GOAMD64="v4"  
GOFLAGS="-v -trimpath"
GHCFLAGS="-O2 -j16 -optc-march=native -optc-O2" 
ZIGFLAGS='-Drelease-safe=true -mcpu=native'

#CPPFLAGS="-D_FORTIFY_SOURCE=2"


PORTAGE_LOGDIR="/run/media/nvme2/logs"

#GENTOO_MIRRORS="http://tux.rainside.sk/gentoo/ \
   # ftp://tux.rainside.sk/gentoo/"



PYTHON_TARGETS="python3_15"  
#python3_13"
PYTHON_SINGLE_TARGET="python3_15"
ROCM_PATH="/usr"
HIP_DEVICE_LIB_PATH="/usr/lib/amdgcn/bitcode"
CMAKE_HIP_FLAGS="${CMAKE_HIP_FLAGS} -O2"
c2@gentoobtw ~ $ 

also here are the results of a benchmark that gave me the confidence to do this. i set the global pythion target to 3_15 and mark set to install every package with the highest possible python version, which gets complicated sense everything that depends on a python pacakge needs the same python version.

Looks like the USE flags are set up right. Some stuff just demands X, so you’re best off adding a file in /etc/portage/package.use/[whatever your file is named] and flipping X on for specific apps, or removing the ‘-X’ from your make.conf and flipping -X per-app. Some examples from my manual-use file:

www-client/firefox hwaccel jumbo-build gtk openh264 gmp-autoupdate system-av1 system-harfbuzz system-icu system-jpeg system-libevent system-libvpx system-pipewire system-png system-webp wayland lto pgo -X
media-libs/libva -X -glx wayland
media-video/libva-utils -X wayland
media-video/mpv -X -xv alsa drm egl lua vulkan archive 

Here’s the list you’ll need for Steam/Winetricks as well:

app-accessibility/at-spi2-core   abi_x86_32
app-arch/bzip2                   abi_x86_32
app-arch/lz4                     abi_x86_32
app-arch/xz-utils                abi_x86_32
app-arch/zstd                    abi_x86_32
app-crypt/p11-kit                abi_x86_32
dev-db/sqlite                    abi_x86_32
dev-lang/orc                     abi_x86_32
dev-lang/rust-bin                abi_x86_32
dev-libs/dbus-glib               abi_x86_32
dev-libs/elfutils                abi_x86_32
dev-libs/expat                   abi_x86_32
dev-libs/fribidi                 abi_x86_32
dev-libs/glib                    abi_x86_32
dev-libs/gmp                     abi_x86_32
dev-libs/icu                     abi_x86_32
dev-libs/json-c                  abi_x86_32
dev-libs/json-glib               abi_x86_32
dev-libs/leancrypto              abi_x86_32
dev-libs/libevdev                abi_x86_32
dev-libs/libffi                  abi_x86_32
dev-libs/libgcrypt               abi_x86_32
dev-libs/libgpg-error            abi_x86_32
dev-libs/libgudev                abi_x86_32
dev-libs/libgusb                 abi_x86_32
dev-libs/libpcre2                abi_x86_32
dev-libs/libtasn1                abi_x86_32
dev-libs/libunistring            abi_x86_32
dev-libs/libusb                  abi_x86_32
dev-libs/libxml2                 abi_x86_32
dev-libs/lzo                     abi_x86_32
dev-libs/nettle                  abi_x86_32
dev-libs/nspr                    abi_x86_32
dev-libs/nss                     abi_x86_32
dev-libs/openssl                 abi_x86_32
dev-libs/wayland                 abi_x86_32
dev-util/spirv-tools             abi_x86_32
dev-util/sysprof-capture         abi_x86_32
gnome-base/librsvg               abi_x86_32
gui-libs/libdecor                abi_x86_32
llvm-core/llvm                   abi_x86_32
media-gfx/graphite2              abi_x86_32
media-libs/a52dec                abi_x86_32
media-libs/alsa-lib              abi_x86_32
media-libs/faad2                 abi_x86_32
media-libs/flac                  abi_x86_32
media-libs/fontconfig            abi_x86_32
media-libs/freetype              abi_x86_32
media-libs/glu                   abi_x86_32
media-libs/graphene              abi_x86_32
media-libs/gst-plugins-bad       abi_x86_32
media-libs/gst-plugins-base      abi_x86_32
media-libs/gst-plugins-good      abi_x86_32
media-libs/gst-plugins-ugly      abi_x86_32
media-libs/gstreamer             abi_x86_32
media-libs/harfbuzz              abi_x86_32
media-libs/lcms                  abi_x86_32
media-libs/libdca                abi_x86_32
media-libs/libdisplay-info	 abi_x86_32
media-libs/libdvdcss             abi_x86_32
media-libs/libdvdnav             abi_x86_32
media-libs/libdvdread            abi_x86_32
media-libs/libepoxy              abi_x86_32
media-libs/libglvnd              abi_x86_32
media-libs/libjpeg-turbo         abi_x86_32
media-libs/libmpeg2              abi_x86_32
media-libs/libogg                abi_x86_32
media-libs/libpng                abi_x86_32
media-libs/libpulse              abi_x86_32
media-libs/libsdl2               abi_x86_32
media-libs/libsndfile            abi_x86_32
media-libs/libva                 abi_x86_32
media-libs/libvorbis             abi_x86_32
media-libs/libwebp               abi_x86_32
media-libs/mesa                  abi_x86_32
media-libs/openal                abi_x86_32
media-libs/opus                  abi_x86_32
media-libs/tiff                  abi_x86_32
media-libs/vulkan-loader         abi_x86_32
media-libs/x264                  abi_x86_32
media-plugins/gst-plugins-a52dec abi_x86_32
media-plugins/gst-plugins-cdparanoia abi_x86_32
media-plugins/gst-plugins-dts    abi_x86_32
media-plugins/gst-plugins-dvdread abi_x86_32
media-plugins/gst-plugins-faad   abi_x86_32
media-plugins/gst-plugins-flac   abi_x86_32
media-plugins/gst-plugins-meta   abi_x86_32
media-plugins/gst-plugins-mpeg2dec abi_x86_32
media-plugins/gst-plugins-mpg123 abi_x86_32
media-plugins/gst-plugins-pulse  abi_x86_32
media-plugins/gst-plugins-resindvd abi_x86_32
media-plugins/gst-plugins-x264   abi_x86_32
media-sound/cdparanoia           abi_x86_32
media-sound/lame                 abi_x86_32
media-sound/mpg123-base          abi_x86_32
media-video/pipewire             abi_x86_32
net-dns/c-ares                   abi_x86_32
net-dns/libidn2                  abi_x86_32
net-libs/gnutls                  abi_x86_32
net-libs/libasyncns              abi_x86_32
net-libs/libndp                  abi_x86_32
net-libs/libpsl                  abi_x86_32
net-libs/nghttp2                 abi_x86_32
net-libs/nghttp3                 abi_x86_32
net-misc/curl                    abi_x86_32
net-misc/networkmanager          abi_x86_32
net-print/cups                   abi_x86_32
sys-apps/dbus                    abi_x86_32
sys-apps/lm-sensors              abi_x86_32
sys-apps/systemd                 abi_x86_32
sys-apps/systemd-utils           abi_x86_32
sys-apps/util-linux              abi_x86_32
sys-libs/gdbm                    abi_x86_32
sys-libs/gpm                     abi_x86_32
sys-libs/libcap                  abi_x86_32
sys-libs/libudev-compat          abi_x86_32
sys-libs/libunwind               abi_x86_32
sys-libs/ncurses                 abi_x86_32
sys-libs/pam                     abi_x86_32
sys-libs/readline                abi_x86_32
sys-libs/zlib                    abi_x86_32
virtual/glu                      abi_x86_32
virtual/libelf                   abi_x86_32
virtual/libiconv                 abi_x86_32
virtual/libintl                  abi_x86_32
virtual/libudev                  abi_x86_32
virtual/libusb                   abi_x86_32
virtual/opengl                   abi_x86_32
virtual/rust                     abi_x86_32
virtual/zlib                     abi_x86_32
x11-libs/cairo                   abi_x86_32
x11-libs/extest                  abi_x86_32
x11-libs/gdk-pixbuf              abi_x86_32
x11-libs/gtk+                    abi_x86_32
x11-libs/libICE                  abi_x86_32
x11-libs/libSM                   abi_x86_32
x11-libs/libX11                  abi_x86_32
x11-libs/libXScrnSaver           abi_x86_32
x11-libs/libXau                  abi_x86_32
x11-libs/libXcomposite           abi_x86_32
x11-libs/libXcursor              abi_x86_32
x11-libs/libXdamage              abi_x86_32
x11-libs/libXdmcp                abi_x86_32
x11-libs/libXext                 abi_x86_32
x11-libs/libXfixes               abi_x86_32
x11-libs/libXft                  abi_x86_32
x11-libs/libXi                   abi_x86_32
x11-libs/libXinerama             abi_x86_32
x11-libs/libXrandr               abi_x86_32
x11-libs/libXrender              abi_x86_32
x11-libs/libXtst                 abi_x86_32
x11-libs/libXv                   abi_x86_32
x11-libs/libXxf86vm              abi_x86_32
x11-libs/libdrm                  abi_x86_32
x11-libs/libpciaccess            abi_x86_32
x11-libs/libvdpau                abi_x86_32
x11-libs/libxcb                  abi_x86_32
x11-libs/libxkbcommon            abi_x86_32
x11-libs/libxshmfence            abi_x86_32
x11-libs/pango                   abi_x86_32
x11-libs/pixman                  abi_x86_32
x11-libs/xcb-util-keysyms        abi_x86_32
x11-misc/colord                  abi_x86_32

I run a 12600KF and a 9060 XT, I don’t know if you’d need some other libs if you have different hardware, I’ve just gone with the list from the Gentoo guide and then removed a couple trouble causers I didn’t need, and then I think added a few that were missing? I kinda just fix stuff if it breaks, I don’t have a master plan for my config files.

You can also reinstall Gentoo with no-multilib and install Steam as a flatpak (and anything else that needs 32-bit), but I like being on the latest mesa drivers so it was worth dealing with multilib for me. And the Steam flatpak can be picky if you try to install to secondary drives.

These two are in my use flags as well:

media-sound/apulse abi_x86_32
net-libs/ngtcp2 abi_x86_32

Not sure what these are required by but I must’ve added them for a reason.

Since you’re using LLMs and they’re essentially massive pattern recognition machines, you can also point them at your configs and they’ll find things you’re missing or should redo. Tis what I did to get my USE file all cleaned up for example, and to help with stripping my kernel of any unneeded modules. Any sort of “read a bunch of information and cross-reference it to each other” task LLMs are wicked at.