I’ve fallen into this pattern where I do an hour or so of self-directed learning in the mornings before going to work. Until recently it was an excellent CMU course on the design of SQL database systems, which I’ve mentioned previously here. I’ve finished that, so I thought I would do something shorter and fun as a break before finding another course to do. I choseĀ The freeCodeCamp.org hot dog or not hot dog tensorflow course. 90 minutes seemed achievable, and I too wish to know if an object in front of me is a hot dog or not.
The course uses Google Colab to walk you through the process. Colab is interesting, I had never used it before and I must say the user interface wasn’t completely obvious to me. One issue is that the workspace keeps timing out — I do my learning in small bursts tetrised around the other things in my life, and Google wants to reap idle workspaces (which is fair). Combined with the quite slow dataset download process this just wasn’t working for me.
But I own computers, some of which have GPUs. I should just be able to run the same code in my homelab right?
Well… That’s a nice theory. It was much harder than I expected. Because my chosen machine has an integrated AMD GPU, I need to use AMD’s ROCm. That means I needed to enter a twisting maze of conflicting python, tensorflow and tensorflow-rocm versions, a typoed GPU version check (yes really), and spend a few hours fighting the incantations and reading reddit posts. Additionally, because I need real physical GPU hardware for this, I can’t just play in a virtual machine. I instead need to risk messing up a physical machine I am somewhat fond of, so that’s nice.
I’ll save you the time. To get tensorflow working on Debian 12 with an AMD GPU, I needed to do the following dance steps…
The version of ROCm I need only supports python 3.9, 3.10, and 3.12. Of course Debian 12 ships with python 3.11 which is the missing option there, so that’s nice. Let’s use pyenv to get a python 3.12 on Debian 12:
sudo apt install -y build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncursesw5-dev \
xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
curl https://pyenv.run | bash
Now add this to your .bashrc:
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
And restart your shell. Now you can install python 3.12:
pyenv install 3.12.11
I like virtualenvs to be in ~/virtualenvs/ so we need to be sneaky making our virtualenv instead of using the pyenv tooling:
${PYENV_ROOT}/versions/3.12.11/bin/python3 -m venv ~/virtualenvs/tensorflow
. ~/virtualenvs/tensorflow/bin/activate
Now we need to install ROCm:
sudo apt update
sudo apt install "linux-headers-$(uname -r)"
sudo apt install -y python3-setuptools python3-wheel libpython3.11
wget <a href="https://repo.radeon.com/amdgpu-install/latest/ubuntu/jammy/amdgpu-install_7.0.1.70001-1_all.deb">https://repo.radeon.com/amdgpu-install/6.4.3/ubuntu/jammy/amdgpu-install_6.4.60403-1_all.deb</a>
sudo apt install ./amdgpu-install_7.0.1.70001-1_all.deb
sudo apt-get update
sudo apt-get install amdgpu-dkms rocm
And now we can go back and install tensorflow and ROCm in our python 3.12 virtualenv:
pip3 install uv
uv pip install tensorflow==2.19.0
uv pip install -U tensorflow-rocm==2.19.0 \
-f https://repo.radeon.com/rocm/manylinux/rocm-rel-7.0/
And now we can run python, import tensorflow, and ask if it has a physical GPU:
$ python3
Python 3.12.11 (main, Sep 21 2025, 08:10:09) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
2025-09-21 08:24:18.780938: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: SSE3 SSE4.1 SSE4.2 AVX AVX2 AVX512F AVX512_VNNI AVX512_BF16 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
>>> print(tf.test.is_gpu_available())
WARNING:tensorflow:From :1: is_gpu_available (from tensorflow.python.framework.test_util) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.config.list_physical_devices('GPU')` instead.
2025-09-21 08:24:25.156483: I external/local_xla/xla/stream_executor/rocm/rocm_executor.cc:920] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2025-09-21 08:24:26.361397: I external/local_xla/xla/stream_executor/rocm/rocm_executor.cc:920] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2025-09-21 08:24:26.361442: I external/local_xla/xla/stream_executor/rocm/rocm_executor.cc:920] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2025-09-21 08:24:26.362540: I external/local_xla/xla/stream_executor/rocm/rocm_executor.cc:920] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2025-09-21 08:24:26.362576: I external/local_xla/xla/stream_executor/rocm/rocm_executor.cc:920] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2025-09-21 08:24:26.362608: I external/local_xla/xla/stream_executor/rocm/rocm_executor.cc:920] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2025-09-21 08:24:26.362630: I tensorflow/core/common_runtime/gpu/gpu_device.cc:2021] Created device /device:GPU:0 with 1982 MB memory: -> device: 0, name: AMD Radeon Graphics, pci bus id: 0000:c6:00.0
True
>>> print(tf.config.list_physical_devices('GPU'))
2025-09-21 08:24:51.553486: I external/local_xla/xla/stream_executor/rocm/rocm_executor.cc:920] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2025-09-21 08:24:51.553590: I external/local_xla/xla/stream_executor/rocm/rocm_executor.cc:920] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2025-09-21 08:24:51.553613: I external/local_xla/xla/stream_executor/rocm/rocm_executor.cc:920] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
>>>
Truly we live in the future.
I have updated this to post use ROCm 7.0.1, it originally used ROCm 6.4.