Skip to content

Commit f1fd862

Browse files
authored
feat: add AMD GPU (amdflang/OpenMP offload) container (#1422)
1 parent 50a0807 commit f1fd862

5 files changed

Lines changed: 128 additions & 30 deletions

File tree

.github/Dockerfile

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,82 @@ ARG CXX_COMPILER
77
ARG FC_COMPILER
88
ARG COMPILER_PATH
99
ARG COMPILER_LD_LIBRARY_PATH
10+
ARG AFAR_VERSION
11+
ARG OLCF_AFAR_ROOT=""
1012

1113
ENV DEBIAN_FRONTEND=noninteractive
1214
ENV TZ=UTC
1315

1416
RUN apt-get update -y && \
15-
apt-get install -y software-properties-common ca-certificates gnupg && \
17+
apt-get install -y software-properties-common ca-certificates gnupg wget && \
1618
add-apt-repository ppa:deadsnakes/ppa && \
1719
apt-get update -y && \
18-
if [ "$TARGET" != "gpu" ]; then \
20+
if [ "$TARGET" = "cpu" ]; then \
1921
apt-get install -y \
2022
build-essential git make cmake gcc g++ gfortran bc \
2123
python3.12 python3.12-venv python3-pip \
2224
openmpi-bin libopenmpi-dev libfftw3-dev \
2325
mpich libmpich-dev; \
24-
else \
26+
elif [ "$TARGET" = "gpu" ]; then \
2527
apt-get install -y \
2628
build-essential git make cmake bc \
2729
python3.12 python3.12-venv python3-pip \
2830
libfftw3-dev \
2931
openmpi-bin libopenmpi-dev; \
32+
elif [ "$TARGET" = "amd" ]; then \
33+
apt-get install -y \
34+
build-essential git make gcc g++ gfortran bc \
35+
python3.12 python3.12-venv python3-pip \
36+
libfftw3-dev libnuma1 libdrm2 libdrm-amdgpu1; \
3037
fi && \
3138
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 2 && \
3239
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
3340

41+
# AMD: download AFAR, install cmake 3.28 (Ubuntu 22.04 ships 3.22 which doesn't
42+
# recognize amdflang as LLVMFlang), then build MPICH with amdflang so the
43+
# generated mpi.mod is compiler-compatible.
44+
RUN if [ "$TARGET" = "amd" ] && [ -n "$AFAR_VERSION" ]; then \
45+
OLCF_AFAR_ROOT="/opt/${AFAR_VERSION}" && \
46+
wget -q "https://repo.radeon.com/rocm/misc/flang/${AFAR_VERSION}-ubuntu.tar.bz2" -O /tmp/afar.tar.bz2 && \
47+
tar -xjf /tmp/afar.tar.bz2 -C /opt/ && \
48+
rm /tmp/afar.tar.bz2 && \
49+
CMAKE_VER=3.28.6 && \
50+
wget -q "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-linux-x86_64.sh" \
51+
-O /tmp/cmake-install.sh && \
52+
chmod +x /tmp/cmake-install.sh && \
53+
/tmp/cmake-install.sh --prefix=/usr/local --skip-license --exclude-subdir && \
54+
rm /tmp/cmake-install.sh && \
55+
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' \
56+
> /usr/local/bin/amdflang-ld-wrap && \
57+
chmod +x /usr/local/bin/amdflang-ld-wrap && \
58+
MPICH_VER=3.4.3 && \
59+
wget -q "https://www.mpich.org/static/downloads/${MPICH_VER}/mpich-${MPICH_VER}.tar.gz" \
60+
-O /tmp/mpich.tar.gz && \
61+
mkdir -p /tmp/mpich-src && \
62+
tar -xzf /tmp/mpich.tar.gz -C /tmp/mpich-src --strip-components=1 && \
63+
cd /tmp/mpich-src && \
64+
FC=/usr/local/bin/amdflang-ld-wrap CC=gcc CXX=g++ \
65+
./configure --prefix=/opt/mpich --enable-shared --disable-static \
66+
--with-device=ch3 2>&1 && \
67+
make -j$(nproc) 2>&1 && \
68+
make install 2>&1 && \
69+
cd / && \
70+
rm -rf /tmp/mpich-src /tmp/mpich.tar.gz; \
71+
fi
72+
3473
ENV OMPI_ALLOW_RUN_AS_ROOT=1
3574
ENV OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
75+
ENV HYDRA_LAUNCHER=fork
3676
ENV PATH="/opt/MFC:$PATH"
3777

3878
COPY ../ /opt/MFC
3979

4080
ENV CC=${CC_COMPILER}
4181
ENV CXX=${CXX_COMPILER}
4282
ENV FC=${FC_COMPILER}
43-
ENV PATH="${COMPILER_PATH}:$PATH"
44-
ENV LD_LIBRARY_PATH="${COMPILER_LD_LIBRARY_PATH}:${LD_LIBRARY_PATH:-}"
83+
ENV OLCF_AFAR_ROOT=${OLCF_AFAR_ROOT}
84+
ENV PATH="${COMPILER_PATH}:/opt/mpich/bin:$PATH"
85+
ENV LD_LIBRARY_PATH="${COMPILER_LD_LIBRARY_PATH}:/opt/mpich/lib:${LD_LIBRARY_PATH:-}"
4586

4687
# Pre-install numpy into the venv before mfc.sh runs, as it's required at
4788
# build time by several dependencies (pandas, cantera, matplotlib, etc.) that
@@ -54,13 +95,17 @@ RUN echo "TARGET=$TARGET CC=$CC_COMPILER FC=$FC_COMPILER" && \
5495
cd /opt/MFC && \
5596
if [ "$TARGET" = "gpu" ]; then \
5697
./mfc.sh build --gpu acc -j $(nproc); \
98+
elif [ "$TARGET" = "amd" ]; then \
99+
./mfc.sh build --gpu mp -j $(nproc); \
57100
else \
58101
./mfc.sh build -j $(nproc); \
59102
fi
60103

61104
RUN cd /opt/MFC && \
62105
if [ "$TARGET" = "gpu" ]; then \
63106
./mfc.sh test -a --dry-run --gpu acc -j $(nproc); \
107+
elif [ "$TARGET" = "amd" ]; then \
108+
./mfc.sh test -a --dry-run --gpu mp -j $(nproc); \
64109
else \
65110
./mfc.sh test -a --dry-run -j $(nproc); \
66111
fi

.github/workflows/docker.yml

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ jobs:
2424
strategy:
2525
matrix:
2626
config:
27-
- { name: 'cpu', runner: 'ubuntu-22.04', base_image: 'ubuntu:22.04' }
28-
- { name: 'cpu', runner: 'ubuntu-22.04-arm', base_image: 'ubuntu:22.04' }
29-
- { name: 'gpu', runner: 'ubuntu-22.04', base_image: 'nvcr.io/nvidia/nvhpc:24.5-devel-cuda_multi-ubuntu22.04', compiler_arch: 'Linux_x86_64' }
30-
- { name: 'gpu', runner: 'ubuntu-22.04-arm', base_image: 'nvcr.io/nvidia/nvhpc:24.5-devel-cuda_multi-ubuntu22.04', compiler_arch: 'Linux_aarch64' }
27+
- { name: 'cpu', tag: 'cpu', runner: 'ubuntu-22.04', base_image: 'ubuntu:22.04' }
28+
- { name: 'cpu', tag: 'cpu', runner: 'ubuntu-22.04-arm', base_image: 'ubuntu:22.04' }
29+
- { name: 'gpu', tag: 'gpu-nvidia', runner: 'ubuntu-22.04', base_image: 'nvcr.io/nvidia/nvhpc:24.5-devel-cuda_multi-ubuntu22.04', compiler_arch: 'Linux_x86_64' }
30+
- { name: 'gpu', tag: 'gpu-nvidia', runner: 'ubuntu-22.04-arm', base_image: 'nvcr.io/nvidia/nvhpc:24.5-devel-cuda_multi-ubuntu22.04', compiler_arch: 'Linux_aarch64' }
31+
- { name: 'amd', tag: 'gpu-amd', runner: 'ubuntu-22.04', base_image: 'ubuntu:22.04' }
3132
runs-on: ${{ matrix.config.runner }}
3233
outputs:
3334
tag: ${{ steps.clone.outputs.tag }}
@@ -108,8 +109,8 @@ jobs:
108109
labels: |
109110
org.opencontainers.image.source=https://github.com/${{ github.repository }}
110111
tags: |
111-
${{ secrets.DOCKERHUB_USERNAME }}/mfc:${{ env.TAG }}-${{ matrix.config.name }}-${{ matrix.config.runner }}
112-
${{ env.GH_REGISTRY }}:${{ env.TAG }}-${{ matrix.config.name }}-${{ matrix.config.runner }}
112+
${{ secrets.DOCKERHUB_USERNAME }}/mfc:${{ env.TAG }}-${{ matrix.config.tag }}-${{ matrix.config.runner }}
113+
${{ env.GH_REGISTRY }}:${{ env.TAG }}-${{ matrix.config.tag }}-${{ matrix.config.runner }}
113114
push: true
114115

115116
- name: Build and push image (gpu)
@@ -130,8 +131,39 @@ jobs:
130131
labels: |
131132
org.opencontainers.image.source=https://github.com/${{ github.repository }}
132133
tags: |
133-
${{ secrets.DOCKERHUB_USERNAME }}/mfc:${{ env.TAG }}-${{ matrix.config.name }}-${{ matrix.config.runner }}
134-
${{ env.GH_REGISTRY }}:${{ env.TAG }}-${{ matrix.config.name }}-${{ matrix.config.runner }}
134+
${{ secrets.DOCKERHUB_USERNAME }}/mfc:${{ env.TAG }}-${{ matrix.config.tag }}-${{ matrix.config.runner }}
135+
${{ env.GH_REGISTRY }}:${{ env.TAG }}-${{ matrix.config.tag }}-${{ matrix.config.runner }}
136+
push: true
137+
138+
- name: Set AMD AFAR vars
139+
if: ${{ matrix.config.name == 'amd' }}
140+
run: |
141+
AFAR=rocm-afar-8873-drop-22.2.0
142+
ROOT="/opt/${AFAR}"
143+
echo "AFAR_VERSION=${AFAR}" >> $GITHUB_ENV
144+
echo "AFAR_ROOT=${ROOT}" >> $GITHUB_ENV
145+
146+
- name: Build and push image (amd)
147+
if: ${{ matrix.config.name == 'amd' }}
148+
uses: docker/build-push-action@v6
149+
with:
150+
context: /mnt/share
151+
file: /mnt/share/Dockerfile
152+
build-args: |
153+
BASE_IMAGE=${{ matrix.config.base_image }}
154+
TARGET=amd
155+
AFAR_VERSION=${{ env.AFAR_VERSION }}
156+
OLCF_AFAR_ROOT=${{ env.AFAR_ROOT }}
157+
CC_COMPILER=gcc
158+
CXX_COMPILER=g++
159+
FC_COMPILER=${{ env.AFAR_ROOT }}/bin/amdflang
160+
COMPILER_PATH=${{ env.AFAR_ROOT }}/lib/llvm/bin:${{ env.AFAR_ROOT }}/bin
161+
COMPILER_LD_LIBRARY_PATH=${{ env.AFAR_ROOT }}/lib:${{ env.AFAR_ROOT }}/lib/llvm/lib
162+
labels: |
163+
org.opencontainers.image.source=https://github.com/${{ github.repository }}
164+
tags: |
165+
${{ secrets.DOCKERHUB_USERNAME }}/mfc:${{ env.TAG }}-gpu-amd-ubuntu-22.04
166+
${{ env.GH_REGISTRY }}:${{ env.TAG }}-gpu-amd-ubuntu-22.04
135167
push: true
136168

137169
manifests:
@@ -169,8 +201,9 @@ jobs:
169201
run: |
170202
GH="${{ env.GH_REGISTRY }}"
171203
for R in "$DH" "$GH"; do
172-
docker buildx imagetools create -t $R:$TAG-cpu $R:$TAG-cpu-ubuntu-22.04 $R:$TAG-cpu-ubuntu-22.04-arm
173-
docker buildx imagetools create -t $R:$TAG-gpu $R:$TAG-gpu-ubuntu-22.04 $R:$TAG-gpu-ubuntu-22.04-arm
204+
docker buildx imagetools create -t $R:$TAG-cpu $R:$TAG-cpu-ubuntu-22.04 $R:$TAG-cpu-ubuntu-22.04-arm
205+
docker buildx imagetools create -t $R:$TAG-gpu-nvidia $R:$TAG-gpu-nvidia-ubuntu-22.04 $R:$TAG-gpu-nvidia-ubuntu-22.04-arm
206+
docker buildx imagetools create -t $R:$TAG-gpu-amd $R:$TAG-gpu-amd-ubuntu-22.04
174207
done
175208
176209
- name: Update latest tags
@@ -181,6 +214,7 @@ jobs:
181214
run: |
182215
GH="${{ env.GH_REGISTRY }}"
183216
for R in "$DH" "$GH"; do
184-
docker buildx imagetools create -t $R:latest-cpu $R:$TAG-cpu-ubuntu-22.04 $R:$TAG-cpu-ubuntu-22.04-arm
185-
docker buildx imagetools create -t $R:latest-gpu $R:$TAG-gpu-ubuntu-22.04 $R:$TAG-gpu-ubuntu-22.04-arm
217+
docker buildx imagetools create -t $R:latest-cpu $R:$TAG-cpu-ubuntu-22.04 $R:$TAG-cpu-ubuntu-22.04-arm
218+
docker buildx imagetools create -t $R:latest-gpu-nvidia $R:$TAG-gpu-nvidia-ubuntu-22.04 $R:$TAG-gpu-nvidia-ubuntu-22.04-arm
219+
docker buildx imagetools create -t $R:latest-gpu-amd $R:$TAG-gpu-amd-ubuntu-22.04
186220
done

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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ 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

0 commit comments

Comments
 (0)