Skip to content

Commit 1557fc4

Browse files
committed
feat: add AMD GPU (amdflang/OpenMP offload) container support
- Dockerfile: add TARGET=amd branch — downloads AFAR drop from repo.radeon.com, installs cmake 3.28 (3.22 doesn't recognise LLVMFlang), builds MPICH 3.4.3 with amdflang so mpi.mod is compiler-compatible; runtime libs libnuma1/libdrm2 added so only --rocm is needed at apptainer runtime - docker.yml: add amd matrix entry + build/push/manifest steps; fix cpu to run natively on amd64/arm64 instead of QEMU cross-build; add weekly nightly cron - CMakeLists.txt: make Cray-specific MPI/hipfft paths conditional on CRAY_MPICH_INC/CRAY_HIPFORT_LIB being set; fall back to standard find_package(MPI) and find_library(hipfft/amdhip64) so the self-contained container image works without any OLCF env vars loaded - toolchain: add amd90a cluster profile (HPCFund gfx90a / MI250); fix module variable export loop so vars that reference previously exported vars expand correctly
1 parent a3e55a9 commit 1557fc4

5 files changed

Lines changed: 114 additions & 18 deletions

File tree

.github/Dockerfile

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,68 @@ ARG CXX_COMPILER
77
ARG FC_COMPILER
88
ARG COMPILER_PATH
99
ARG COMPILER_LD_LIBRARY_PATH
10+
ARG AFAR_VERSION
1011

1112
ENV DEBIAN_FRONTEND=noninteractive
1213
ENV TZ=UTC
1314

1415
RUN apt-get update -y && \
15-
apt-get install -y software-properties-common ca-certificates gnupg && \
16+
apt-get install -y software-properties-common ca-certificates gnupg wget && \
1617
add-apt-repository ppa:deadsnakes/ppa && \
1718
apt-get update -y && \
18-
if [ "$TARGET" != "gpu" ]; then \
19+
if [ "$TARGET" = "cpu" ]; then \
1920
apt-get install -y \
2021
build-essential git make cmake gcc g++ gfortran bc \
2122
python3.12 python3.12-venv python3-pip \
2223
openmpi-bin libopenmpi-dev libfftw3-dev \
2324
mpich libmpich-dev; \
24-
else \
25+
elif [ "$TARGET" = "gpu" ]; then \
2526
apt-get install -y \
2627
build-essential git make cmake bc \
2728
python3.12 python3.12-venv python3-pip \
2829
libfftw3-dev \
2930
openmpi-bin libopenmpi-dev; \
31+
elif [ "$TARGET" = "amd" ]; then \
32+
apt-get install -y \
33+
build-essential git make gcc g++ gfortran bc \
34+
python3.12 python3.12-venv python3-pip \
35+
libfftw3-dev libnuma1 libdrm2 libdrm-amdgpu1; \
3036
fi && \
3137
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 2 && \
3238
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
3339

40+
# AMD: download AFAR, install cmake 3.28 (Ubuntu 22.04 ships 3.22 which doesn't
41+
# recognize amdflang as LLVMFlang), then build MPICH with amdflang so the
42+
# generated mpi.mod is compiler-compatible.
43+
RUN if [ "$TARGET" = "amd" ] && [ -n "$AFAR_VERSION" ]; then \
44+
OLCF_AFAR_ROOT="/opt/${AFAR_VERSION}" && \
45+
wget -q "https://repo.radeon.com/rocm/misc/flang/${AFAR_VERSION}-ubuntu.tar.bz2" -O /tmp/afar.tar.bz2 && \
46+
tar -xjf /tmp/afar.tar.bz2 -C /opt/ && \
47+
rm /tmp/afar.tar.bz2 && \
48+
CMAKE_VER=3.28.6 && \
49+
wget -q "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-linux-x86_64.sh" \
50+
-O /tmp/cmake-install.sh && \
51+
chmod +x /tmp/cmake-install.sh && \
52+
/tmp/cmake-install.sh --prefix=/usr/local --skip-license --exclude-subdir && \
53+
rm /tmp/cmake-install.sh && \
54+
printf '#!/bin/bash\nargs=()\nwhile [ "$#" -gt 0 ]; do\n if [ "$1" = "-soname" ]; then\n args+=("-Wl,-soname,$2"); shift 2\n else\n args+=("$1"); shift\n fi\ndone\nexec '"${OLCF_AFAR_ROOT}"'/bin/amdflang "${args[@]}"\n' \
55+
> /usr/local/bin/amdflang-ld-wrap && \
56+
chmod +x /usr/local/bin/amdflang-ld-wrap && \
57+
MPICH_VER=3.4.3 && \
58+
wget -q "https://www.mpich.org/static/downloads/${MPICH_VER}/mpich-${MPICH_VER}.tar.gz" \
59+
-O /tmp/mpich.tar.gz && \
60+
mkdir -p /tmp/mpich-src && \
61+
tar -xzf /tmp/mpich.tar.gz -C /tmp/mpich-src --strip-components=1 && \
62+
cd /tmp/mpich-src && \
63+
FC=/usr/local/bin/amdflang-ld-wrap CC=gcc CXX=g++ \
64+
./configure --prefix=/opt/mpich --enable-shared --disable-static \
65+
--with-device=ch3 2>&1 && \
66+
make -j$(nproc) 2>&1 && \
67+
make install 2>&1 && \
68+
cd / && \
69+
rm -rf /tmp/mpich-src /tmp/mpich.tar.gz; \
70+
fi
71+
3472
ENV OMPI_ALLOW_RUN_AS_ROOT=1
3573
ENV OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
3674
ENV PATH="/opt/MFC:$PATH"
@@ -40,8 +78,9 @@ COPY ../ /opt/MFC
4078
ENV CC=${CC_COMPILER}
4179
ENV CXX=${CXX_COMPILER}
4280
ENV FC=${FC_COMPILER}
43-
ENV PATH="${COMPILER_PATH}:$PATH"
44-
ENV LD_LIBRARY_PATH="${COMPILER_LD_LIBRARY_PATH}:${LD_LIBRARY_PATH:-}"
81+
ENV OLCF_AFAR_ROOT=/opt/${AFAR_VERSION}
82+
ENV PATH="${COMPILER_PATH}:/opt/mpich/bin:$PATH"
83+
ENV LD_LIBRARY_PATH="${COMPILER_LD_LIBRARY_PATH}:/opt/mpich/lib:${LD_LIBRARY_PATH:-}"
4584

4685
# Pre-install numpy into the venv before mfc.sh runs, as it's required at
4786
# build time by several dependencies (pandas, cantera, matplotlib, etc.) that
@@ -54,13 +93,17 @@ RUN echo "TARGET=$TARGET CC=$CC_COMPILER FC=$FC_COMPILER" && \
5493
cd /opt/MFC && \
5594
if [ "$TARGET" = "gpu" ]; then \
5695
./mfc.sh build --gpu -j $(nproc); \
96+
elif [ "$TARGET" = "amd" ]; then \
97+
./mfc.sh build --gpu mp -j $(nproc); \
5798
else \
5899
./mfc.sh build -j $(nproc); \
59100
fi
60101

61102
RUN cd /opt/MFC && \
62103
if [ "$TARGET" = "gpu" ]; then \
63104
./mfc.sh test -a --dry-run --gpu -j $(nproc); \
105+
elif [ "$TARGET" = "amd" ]; then \
106+
./mfc.sh test -a --dry-run --gpu mp -j $(nproc); \
64107
else \
65108
./mfc.sh test -a --dry-run -j $(nproc); \
66109
fi

.github/workflows/docker.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jobs:
2424
- { name: 'cpu', runner: 'ubuntu-22.04-arm', base_image: 'ubuntu:22.04' }
2525
- { name: 'gpu', runner: 'ubuntu-22.04', base_image: 'nvcr.io/nvidia/nvhpc:23.11-devel-cuda_multi-ubuntu22.04' }
2626
- { name: 'gpu', runner: 'ubuntu-22.04-arm', base_image: 'nvcr.io/nvidia/nvhpc:23.11-devel-cuda_multi-ubuntu22.04' }
27+
- { name: 'amd', runner: 'ubuntu-22.04', base_image: 'ubuntu:22.04' }
2728
runs-on: ${{ matrix.config.runner }}
2829
outputs:
2930
tag: ${{ steps.clone.outputs.tag }}
@@ -113,6 +114,24 @@ jobs:
113114
tags: ${{ secrets.DOCKERHUB_USERNAME }}/mfc:${{ env.TAG }}-${{ matrix.config.name }}-${{ matrix.config.runner}}
114115
push: true
115116

117+
- name: Build and push image (amd)
118+
if: ${{ matrix.config.name == 'amd' }}
119+
uses: docker/build-push-action@v6
120+
with:
121+
context: /mnt/share
122+
file: /mnt/share/Dockerfile
123+
build-args: |
124+
BASE_IMAGE=${{ matrix.config.base_image }}
125+
TARGET=amd
126+
AFAR_VERSION=rocm-afar-8873-drop-22.2.0
127+
CC_COMPILER=gcc
128+
CXX_COMPILER=g++
129+
FC_COMPILER=/opt/rocm-afar-8873-drop-22.2.0/bin/amdflang
130+
COMPILER_PATH=/opt/rocm-afar-8873-drop-22.2.0/lib/llvm/bin:/opt/rocm-afar-8873-drop-22.2.0/bin
131+
COMPILER_LD_LIBRARY_PATH=/opt/rocm-afar-8873-drop-22.2.0/lib:/opt/rocm-afar-8873-drop-22.2.0/lib/llvm/lib
132+
tags: ${{ secrets.DOCKERHUB_USERNAME }}/mfc:${{ env.TAG }}-amd-ubuntu-22.04
133+
push: true
134+
116135
manifests:
117136
runs-on: ubuntu-latest
118137
needs: Container
@@ -133,6 +152,7 @@ jobs:
133152
run: |
134153
docker buildx imagetools create -t $REGISTRY:$TAG-cpu $REGISTRY:$TAG-cpu-ubuntu-22.04 $REGISTRY:$TAG-cpu-ubuntu-22.04-arm
135154
docker buildx imagetools create -t $REGISTRY:$TAG-gpu $REGISTRY:$TAG-gpu-ubuntu-22.04 $REGISTRY:$TAG-gpu-ubuntu-22.04-arm
155+
docker buildx imagetools create -t $REGISTRY:$TAG-amd $REGISTRY:$TAG-amd-ubuntu-22.04
136156
137157
- name: Update latest tags
138158
if: github.event_name == 'release'
@@ -142,3 +162,4 @@ jobs:
142162
run: |
143163
docker buildx imagetools create -t $REGISTRY:latest-cpu $REGISTRY:$TAG-cpu-ubuntu-22.04 $REGISTRY:$TAG-cpu-ubuntu-22.04-arm
144164
docker buildx imagetools create -t $REGISTRY:latest-gpu $REGISTRY:$TAG-gpu-ubuntu-22.04 $REGISTRY:$TAG-gpu-ubuntu-22.04-arm
165+
docker buildx imagetools create -t $REGISTRY:latest-amd $REGISTRY:$TAG-amd-ubuntu-22.04

CMakeLists.txt

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -563,10 +563,11 @@ exit 0
563563
find_package(MPI COMPONENTS Fortran REQUIRED)
564564

565565
target_compile_definitions(${a_target} PRIVATE MFC_MPI)
566-
if(CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
566+
if(CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND
567+
DEFINED ENV{CRAY_MPICH_INC} AND NOT "$ENV{CRAY_MPICH_INC}" STREQUAL "")
567568
target_compile_options(${a_target} PRIVATE "$ENV{CRAY_MPICH_INC}")
568569
target_link_libraries(${a_target} PRIVATE $ENV{CRAY_MPICH_LIB})
569-
else()
570+
else()
570571
target_link_libraries(${a_target} PRIVATE MPI::MPI_Fortran)
571572
endif()
572573
endif()
@@ -587,10 +588,16 @@ exit 0
587588
find_package(CUDAToolkit REQUIRED)
588589
target_link_libraries(${a_target} PRIVATE CUDA::cudart CUDA::cufft)
589590
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
590-
target_link_libraries(${a_target} PRIVATE $ENV{CRAY_HIPFORT_LIB})
591-
else()
591+
if(DEFINED ENV{CRAY_HIPFORT_LIB} AND NOT "$ENV{CRAY_HIPFORT_LIB}" STREQUAL "")
592+
target_link_libraries(${a_target} PRIVATE $ENV{CRAY_HIPFORT_LIB})
593+
else()
594+
find_library(HIPFFT_LIB hipfft
595+
HINTS "$ENV{OLCF_AFAR_ROOT}/lib" REQUIRED)
596+
target_link_libraries(${a_target} PRIVATE ${HIPFFT_LIB})
597+
endif()
598+
else()
592599
find_package(hipfort COMPONENTS hipfft CONFIG REQUIRED)
593-
target_link_libraries(${a_target} PRIVATE hipfort::hipfft)
600+
target_link_libraries(${a_target} PRIVATE hipfort::hipfft)
594601
endif()
595602
else()
596603
find_package(FFTW REQUIRED)
@@ -703,8 +710,14 @@ exit 0
703710
PRIVATE -DFRONTIER_UNIFIED)
704711
endif()
705712

706-
find_package(hipfort COMPONENTS hip CONFIG REQUIRED)
707-
target_link_libraries(${a_target} PRIVATE hipfort::hip hipfort::hipfort-amdgcn flang_rt.hostdevice)
713+
find_library(HIP_LIB amdhip64
714+
HINTS "$ENV{OLCF_AFAR_ROOT}/lib" REQUIRED)
715+
find_library(HIPFORT_AMDGCN_LIB hipfort-amdgcn
716+
HINTS "$ENV{OLCF_AFAR_ROOT}/lib" REQUIRED)
717+
target_include_directories(${a_target} PRIVATE
718+
"$ENV{OLCF_AFAR_ROOT}/include/hipfort/amdgcn")
719+
target_link_libraries(${a_target} PRIVATE
720+
${HIP_LIB} ${HIPFORT_AMDGCN_LIB} flang_rt.hostdevice)
708721
endif()
709722
elseif (CMAKE_Fortran_COMPILER_ID STREQUAL "Cray")
710723
target_compile_options(${a_target} PRIVATE "SHELL:-h noacc" "SHELL:-x acc")

toolchain/bootstrap/modules.sh

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ fi
105105

106106
ELEMENTS="$(__extract "$u_c-all") $(__extract "$u_c-$cg")"
107107
MODULES=`echo "$ELEMENTS" | tr ' ' '\n' | grep -v = | xargs`
108-
VARIABLES=`echo "$ELEMENTS" | tr ' ' '\n' | grep = | xargs`
109108

110109
log " $ module load $MODULES"
111110
if ! module load $MODULES; then
@@ -114,10 +113,17 @@ if ! module load $MODULES; then
114113
return
115114
fi
116115

117-
if [ $(echo "$VARIABLES" | grep = | wc -c) -gt 0 ]; then
118-
log " $ export $(eval "echo $VARIABLES")"
119-
export $(eval "echo $VARIABLES") > /dev/null
120-
fi
116+
# Export variables one line at a time so each can reference previously exported vars
117+
# (e.g. PATH="${OLCF_AFAR_ROOT}/..." requires OLCF_AFAR_ROOT to already be set)
118+
for _suffix in "all" "$cg"; do
119+
while IFS= read -r _entry; do
120+
if echo "$_entry" | grep -q '='; then
121+
log " $ export $(eval "echo \"$_entry\"")"
122+
eval "export $_entry"
123+
fi
124+
done < <(grep -E "^$u_c-$_suffix\s+" toolchain/modules | sed "s/^$u_c-$_suffix\s\+//")
125+
done
126+
unset _suffix _entry
121127

122128
UNLOAD_MODULES="$(__extract "$u_c-all-unload") $(__extract "$u_c-$cg-unload")"
123129
UNLOAD_MODULES=$(echo "$UNLOAD_MODULES" | xargs)

toolchain/modules

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,24 @@ f-all cpe/25.03 rocm/6.3.1
4646
f-all cray-fftw cray-hdf5 python cmake
4747
f-gpu python craype-accel-amd-gfx90a rocprofiler-compute/3.0.0
4848

49-
famd OLCF Frontier AMD
49+
famd OLCF Frontier AMD
5050
famd-all python cmake
5151
famd-all cpe/25.09
5252
famd-all PrgEnv-amd
5353

54+
amd90a HPCFund gfx90a compiler (MI250)
55+
amd90a-gpu rocm/7.2.0
56+
amd90a-gpu OLCF_AFAR_ROOT="/work1/spencerbryngelson/sbryngelson/software/therock-afar-23.2.1-gfx90a-7.13.0-7357b5084b"
57+
amd90a-gpu PATH="${OLCF_AFAR_ROOT}/lib/llvm/bin:${PATH}"
58+
amd90a-gpu LD_LIBRARY_PATH="${OLCF_AFAR_ROOT}/lib:${OLCF_AFAR_ROOT}/lib/llvm/lib:${LD_LIBRARY_PATH}"
59+
amd90a-gpu CRAY_HIPFORT_INC="-I${OLCF_AFAR_ROOT}/include/hipfort/amdgcn"
60+
amd90a-gpu CRAY_HIPFORT_LIB="-L${OLCF_AFAR_ROOT}/lib -lhipfft"
61+
amd90a-gpu CRAY_HIP_INC="-I${OLCF_AFAR_ROOT}/include/hip"
62+
amd90a-gpu CMAKE_PREFIX_PATH="${OLCF_AFAR_ROOT}:${CMAKE_PREFIX_PATH}"
63+
amd90a-gpu CC="${OLCF_AFAR_ROOT}/lib/llvm/bin/clang"
64+
amd90a-gpu CXX="${OLCF_AFAR_ROOT}/lib/llvm/bin/clang++"
65+
amd90a-gpu FC="${OLCF_AFAR_ROOT}/bin/amdflang"
66+
5467
tuo OLCF Tuolumne
5568
tuo-all cpe/25.03 rocm/6.3.1
5669
tuo-all cray-fftw/3.3.10.9 cray-hdf5 python/3.12.2 cmake

0 commit comments

Comments
 (0)