IBM POWER9 AC922 for Digital Forensics and Artificial Intelligence
My IBM POWER9 AC922 has been a long-running engineering platform since 2019 for digital forensics and AI work involving AltiVec/VSX, OpenMP, CUDA, Tesla V100, dlib, MXNet, FAISS, ArcFace, Kaldi, Vosk, whisper.cpp, OCR, file carving, and current CTranslate2/faster-whisper experiments.
Compiling software on x86-64 and making it run efficiently, reproducibly, and sustainably on a different processor architecture are not the same problem. Once prebuilt binaries, x86-oriented optimizations, and familiar toolchains disappear, application development often starts with the compiler, instruction set, memory-access pattern, threading model, and the relationship between the host processor and its accelerators.
Since 2019, the IBM Power System AC922 I have used in digital forensics and artificial intelligence work within the Republic of Türkiye Ministry of Interior has been one of the systems on which I experienced this distinction most clearly. Over time it became a common compute platform for face recognition, speech recognition, image and audio processing, OCR, large-scale vector search, file carving, cryptanalysis, SIMD optimization, OpenMP, and CUDA work.
Its value to me is not simply that I had access to a powerful server. POWER9 is outside the mainstream x86 path, and the frequent absence of ready-made packages forced me into library source code, compiler options, vector instructions, memory locality, and GPU kernels. As I now prepare to run CTranslate2 and faster-whisper on the same machine, I am effectively returning to a newer version of the architecture problem I first faced with dlib, MXNet, and FAISS years ago.
AC922 Hardware Architecture and NVLink Topology
The system I use is an IBM Power System AC922 8335-GTH. It is a specialized AI and high-performance-computing platform that combines two POWER9 processor sockets with NVIDIA Tesla V100 accelerators over NVLink 2.0. The GTH is the air-cooled model and supports up to four GPUs; the six-GPU configuration belongs to the water-cooled GTX model. My system contains four NVIDIA Tesla V100 SXM2 32 GB GPUs.
On the CPU side there are 32 physical POWER9 cores. SMT4 exposes 128 logical processors to the operating system. The system has 512 GiB of DDR4 memory. Each V100 contains 32 GB of local HBM2 memory, giving 128 GB of aggregate physical HBM2 across the four GPUs, although this is not one unified 128 GB address space.
One of the architectural features that separates the AC922 from a conventional x86 + PCIe GPU node is its NVLink 2.0 topology. NVLink is not used only for GPU-to-GPU communication here: the V100 GPUs are connected directly to the POWER9 processors over NVLink, with coherent access to GPU memory. This does not eliminate data-movement cost, but it changes the bandwidth and latency characteristics of the CPU-GPU path compared with a host-device path built only around PCIe. It is one of the concrete reasons why I have treated data movement as part of algorithm optimization on this platform.
A single V100 SXM2 32 GB provides 5,120 CUDA cores, 640 Tensor Cores, about 900 GB/s of HBM2 bandwidth, 15.7 TFLOPS FP32, and 125 Tensor TFLOPS FP16. Across four cards, the theoretical totals are 20,480 CUDA cores, 2,560 Tensor Cores, about 62.8 TFLOPS FP32, and about 500 Tensor TFLOPS FP16. These numbers do not imply that one workload will automatically become four times faster. Scaling depends on partitionability, inter-GPU communication, synchronization, kernel design, and movement between host and device memory.
An AC922 of this class is still not an ordinary development machine. The combination of POWER9, SXM2 V100, NVLink, and a large memory footprint in one node makes it architecturally different from a conventional x86 server with PCIe GPUs. For me, that difference has repeatedly become visible across very different problem domains.
From x86 Assumptions to AltiVec and VSX
One of the first difficult areas on POWER9 was face-recognition work with dlib and MXNet. Source code could appear portable, yet performance-critical paths often contained assumptions about SSE, AVX, or AVX2. Getting the code to compile and making it use the target architecture effectively were two different tasks.
I therefore adapted some instruction-set-dependent sections to the AltiVec/VSX vector facilities of POWER. This was not simply a matter of renaming intrinsics. Vector-register behavior, alignment requirements, compiler code generation, load/store layout, and cache behavior all had to be considered together.
Those projects made one SIMD lesson particularly clear: wider vector instructions do not guarantee speed by themselves. If data is scattered in memory, cache locality is poor, or branch cost is high, theoretical vector width cannot be fully exploited. In later optimization work I therefore began with data layout before instruction selection.
I ran many experimental benchmarks on different software revisions, but I do not publish reconstructed percentage speedups without recreating the same software and hardware conditions. Historical optimization results therefore remain qualitative here, while hardware specifications and version boundaries are stated with verifiable numbers.
FAISS and ArcFace: The Problem After the Model
In face-recognition work using ArcFace models to extract embeddings from large data sets, the next major problem was similarity search. Fast feature extraction does not remove the cost of searching millions of vectors.
Building FAISS on POWER9 was far from a standard package installation at the time. After a lengthy compilation and compatibility process, I got it running and modified parts of the code for the architecture. The experience reinforced that a face-recognition system is not just a neural network: GPU embedding generation, CPU-side preparation, index memory behavior, and the search algorithm are parts of the same performance chain.
That changed the question from "how fast is the model?" to "how fast is the complete path?" End-to-end throughput, data movement, and index access became as important as inference latency.
Kaldi, Vosk, and whisper.cpp for Speech Recognition
I also developed speech and audio-processing systems on the same machine for years. I first worked with Kaldi and Vosk. When the Whisper family appeared, I built and ran whisper.cpp on POWER9 and moved part of my speech-recognition work to that model family.
The C/C++ implementation of whisper.cpp matched the way I was already working. Thread count, SIMD paths, build options, tensor operations, and memory behavior were not completely hidden behind a framework layer. My earlier low-level POWER9 work and newer speech-recognition models therefore connected naturally.
Real-Time Television Stream Analysis
One of the more complex systems I developed on the machine split a live television stream into multiple analysis channels on the same timeline. FFmpeg separated the media into audio and video, and the data was passed to separate workers through inter-process pipes.
The video path periodically extracted frames for face recognition and used Tesseract to read on-screen text. The audio path performed speech recognition and passed recognized text to later content analysis. The experimental application used a predefined reference face gallery; detected faces were compared against that gallery while visual identity, on-screen text, recognized speech, and timing information were correlated on the same media timeline.
The engineering problem was not the contents of the gallery, but correlating image, OCR, and speech-recognition output under a common time base. I was working with the practical form of what is now commonly described as multimodal processing while integrating different models into the same stream.
OpenMP, SMT, and Real Parallelism
A significant portion of my work was written in C and C++. OpenMP was one of my primary tools for CPU parallelism. The 32 physical POWER9 cores and 128 logical processors exposed through SMT4 create substantial parallel capacity for suitable workloads, but adding #pragma omp parallel for does not automatically make an algorithm faster.
Execution time is determined not only by computation but also by synchronization, memory access, I/O, load imbalance, and cache effects. In some workloads I observed 128 software threads performing worse than 32. This is not contradictory: SMT does not multiply physical execution units. If compute resources or memory bandwidth are already saturated, more threads can add scheduling and cache pressure instead of useful work.
I therefore treated OpenMP and SIMD as two levels of parallelism rather than competing techniques. Work can be divided across cores while each core uses its VSX vector path. This only works efficiently when data placement, cache-line sharing, NUMA boundaries, and memory bandwidth are designed with both levels in mind.
CUDA C/C++ and Four Tesla V100 GPUs
I did not use the V100 GPUs only through high-level frameworks. I wrote CUDA C/C++ kernels, maintained .cu and .cuh sources, compiled them with nvcc, and distributed selected workloads across all four GPUs.
GPU programming exposed the same fundamental rule as CPU optimization: theoretical FLOPS cannot be separated from data movement. For small jobs, host-device copies and kernel-launch overhead can erase the gain. For large matrix operations, bulk embedding extraction, and workloads with high arithmetic intensity, HBM2 bandwidth and V100 compute resources change the balance.
A four-GPU system also does not require every workload to be split across all devices. For independent jobs, one worker per GPU can provide more predictable throughput, fault isolation, and resource management. That is also one of the first topologies I plan to benchmark for faster-whisper.
File Carving over Large Raw Data
In digital forensics, I developed file-carving systems over large dump data. I ported an approach I had previously implemented in C# to C/C++ and parallelized it with OpenMP.
At scale, the problem is not simply finding file-header and footer signatures. Search windows need enough overlap for signatures that cross block boundaries, adjacent workers must not emit duplicate findings, disk I/O must be balanced against CPU scanning speed, and false positives need to be constrained. Block size, overlap, signature-search strategy, and parallelism therefore have to be designed together.
Although this looks very different from face or speech recognition, I treated it as the same optimization discipline: minimize unnecessary copies, avoid rescanning the same region, and size parallelism according to real storage throughput.
AES, SIMD, and Small Costs Repeated Billions of Times
I also used POWER vector facilities and parallel compute capacity in experimental AES cryptanalysis work. Cryptanalytic workloads make the cost of an instruction, branch, or memory access unusually visible because a tiny operation can be repeated billions of times.
That work affected the way I approached later optimization projects. I stopped thinking of optimization as simply adding more cores or GPUs and increasingly focused on reducing total data movement, repeated work, and synchronization.
Different Data Types on the Same Machine
Over the years, the AC922 brought very different data classes onto the same compute node. I used it for face recognition, ArcFace embedding extraction, and frame analysis; Kaldi, Vosk, whisper.cpp, and speech recognition; FFmpeg-based real-time media decomposition; Tesseract OCR; FAISS similarity search; parallel file carving over raw disk and dump data; and AES-focused cryptanalytic experiments.
Reproducibility in Digital Forensics
For digital forensics, one of the most important lessons from AI work on this system was not speed but the need to record how a machine-generated result was produced.
The same audio file or image can be processed through different CPU SIMD paths, CUDA kernels, library versions, or floating-point reduction orders. The mathematical model may be nominally identical while the physical execution path differs. Small numerical differences usually do not matter, but near a decision boundary they can propagate into a different token or classification decision.
For that reason, identifying an AI-derived result only by model name is insufficient in a forensic workflow. At minimum, the input hash, model-file hash, model and inference-engine version, processor architecture, GPU model, CUDA/cuDNN versions, compute type, decoding parameters, and timestamps should be recorded together.
This metadata does not replace evidence integrity or chain-of-custody controls. It describes the execution environment that produced a derived result and makes later reproduction and comparison possible. In my view, a "deterministic" AI workflow does not mean promising bit-for-bit identical output under every hardware condition. GPU floating-point execution may make that unrealistic. The engineering objective is to record the variables so that any difference can be traced to a documented execution context.
2026: Returning to the Same Problem with CTranslate2
One of my current goals is to run CTranslate2/faster-whisper-based Whisper models on this machine. As of 21 August 2026, mainstream prebuilt CTranslate2 Linux binaries remain focused on x86-64 and AArch64, so ppc64le brings the source tree, compiler, and backend configuration back into the foreground.
As of the same date, the POWER10/ppc64le contribution is still open. It targets VSX together with POWER10 Matrix Math Accelerator units and explicitly notes that a POWER9 build may be possible while the absence of MMA units would have a significant effect on CPU performance. A POWER10 path should therefore not be treated as a POWER9 performance promise.
The GPU side remains useful. V100 is a compute capability 7.0 Volta GPU, or sm_70; for a CTranslate2 source build it is therefore preferable to pin the target explicitly with CUDA_ARCH_LIST=7.0. I plan to establish the first reference run with one V100, FP16, a fixed model, and fixed decoding parameters. The primary metric will be RTF (real-time factor), accompanied by wall-clock time, peak GPU memory, GPU utilization, WER when a reference transcript is available, and normalized output differences across GPU0 through GPU3. Token/s can be a secondary metric, but for speech recognition it is less informative on its own than RTF. For batch or concurrent speech workloads, four independent inference workers are also one of the topologies I intend to evaluate.
The Real Platform Constraint
The most important current boundary comes from CUDA. NVIDIA removed PowerPC support in CUDA 12.5. The final official CUDA line for POWER9 is therefore 12.4.x, and the CUDA 12.4.1 Linux support matrix lists POWER9 on RHEL 8 through 8.9. The cuDNN 9.0 documentation also includes rhel8/ppc64le installation and a CUDA 12 package.
CTranslate2 4.5.0 moved the Python package to cuDNN 9 and removed compatibility with cuDNN 8, which makes version pinning even more important on this platform. CTranslate2, CUDA, and cuDNN should therefore be treated as one validated combination rather than independently selected components.
By contrast, the open CTranslate2 POWER10 contribution documents its CPU-side test environment around RHEL 9 and IBM Advance Toolchain 17. These statements describe two different things: NVIDIA's supported POWER9 GPU platform and the test environment of an in-development POWER10 CPU path. For a POWER9 + V100 deployment, the NVIDIA-supported GPU base is the stronger constraint. My rational target is therefore RHEL 8.9, CUDA 12.4.1, a compatible cuDNN 9 release, and a POWER9-specific source build.
The server still runs an older operating-system and NVIDIA-driver generation, so I do not consider an in-place blind upgrade appropriate. Firmware, GPU driver, NVLink topology, and application dependencies need to be validated together, ideally in a new system environment before the currently working setup is replaced.
The Common Lesson after Seven Years
The line that began in 2019 with adapting dlib and MXNet paths to AltiVec/VSX continued through FAISS, ArcFace, Kaldi, Vosk, whisper.cpp, OpenMP, CUDA, Tesseract, and file-carving work. In 2026, the same machine is again an experimental platform for CTranslate2, faster-whisper, and newer local AI models.
The common element is not a framework. In every case, the algorithm eventually becomes processor instructions, memory accesses, I/O, synchronization, and data movement. The scarcity of ready-made packages on POWER9 created extra engineering work, but it also kept the layers between the algorithm and the hardware visible.
The AC922 is therefore more than a rare server with four V100 GPUs and 512 GiB of memory to me. It has been a long-running engineering laboratory for architecture awareness, parallel programming, SIMD, GPU programming, reproducibility, algorithm optimization, and the intersection of digital forensics and artificial intelligence.
The most durable principle I took from it is still this: The real power of hardware is not the FLOPS value printed in its specification sheet. You possess that power only to the extent that you can build the algorithm, data layout, and execution model capable of using it.
Sources
- IBM Redbooks. IBM Power System AC922 Technical Overview and Introduction. 2018; updated 2023. https://www.redbooks.ibm.com/abstracts/redp5494.html
- IBM Support. POWER9/NVLink 2.0 CPU-GPU connectivity on IBM Power System AC922. 2021. https://www.ibm.com/support/pages/node/6412651
- IBM Documentation. 8335-GTH/GTX parts and GPU configuration. Accessed 2026. https://www.ibm.com/docs/en/power9/8335-GTX?topic=fpl-8335-gtc-8335-gtg-8335-gth-8335-gtw-8335-gtx-parts
- NVIDIA. Tesla V100 Tensor Core GPU Datasheet. 2017. https://images.nvidia.com/content/technologies/volta/pdf/tesla-volta-v100-datasheet.pdf
- NVIDIA. CUDA Installation Guide for Linux 12.4 Update 1. 2024. https://docs.nvidia.com/cuda/archive/12.4.1/cuda-installation-guide-linux/index.html
- NVIDIA. CUDA Toolkit 12.5 Release Notes. 2024. https://docs.nvidia.com/cuda/archive/12.5.0/cuda-toolkit-release-notes/index.html
- NVIDIA. cuDNN 9.0 Linux Installation. 2024. https://docs.nvidia.com/deeplearning/cudnn/backend/v9.0.0/installation/linux.html
- OpenNMT/CTranslate2. CTranslate2 4.5.0 Release Notes. 2024. https://github.com/OpenNMT/CTranslate2/releases/tag/v4.5.0
- OpenNMT/CTranslate2. IBM Power10 (VSX, MMA) support for ppc64le, PR #1748. 2023-2026. https://github.com/OpenNMT/CTranslate2/pull/1748