Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v0.4.0 #25

Merged
merged 27 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c737975
GPU Support
AndrewPlayer3 Apr 29, 2024
ae59337
Move CUDA installation to script for conditional install
AndrewPlayer3 Apr 29, 2024
f697e19
removed path export
AndrewPlayer3 Apr 29, 2024
84255e8
removed gpuarch code (wont work during docker build)
AndrewPlayer3 Apr 29, 2024
de98536
updated changelog
AndrewPlayer3 Apr 29, 2024
f8c4210
change things to not use gpu by default
AndrewPlayer3 Apr 30, 2024
38a610e
Merge branch 'develop' into nvidia
forrestfwilliams May 7, 2024
53f4a36
combine cpu/gpu build proc
forrestfwilliams May 7, 2024
1ca96e4
correct script name
forrestfwilliams May 7, 2024
9e9b0ec
update arg logic
forrestfwilliams May 7, 2024
2d9cb3e
changed from yes to true
AndrewPlayer3 May 8, 2024
1cd89b3
make gpu not default
AndrewPlayer3 May 8, 2024
2935dfd
add cuda paths using docker's ENV rather than .bashrc
AndrewPlayer3 May 8, 2024
0cdbcec
use cuda base image for GPU
forrestfwilliams May 9, 2024
cb80b36
Merge branch 'nvidia' into gpu
forrestfwilliams May 9, 2024
d1d89c0
Merge pull request #24 from ASFHyP3/gpu
forrestfwilliams May 9, 2024
cf1033c
swith to use of process_parallel for gpu case
forrestfwilliams May 9, 2024
2725a0f
fix unzip download option
forrestfwilliams May 9, 2024
a6f6cf9
fix small bugs
forrestfwilliams May 9, 2024
e1518ca
swith back to using sentinel_scene_multigpu
forrestfwilliams May 9, 2024
3602d7d
fix new bugs
forrestfwilliams May 9, 2024
661cc2a
fix small bugs
forrestfwilliams May 13, 2024
131f30c
cleanup
forrestfwilliams May 13, 2024
b6c9a11
add ec2 instructions to readme
forrestfwilliams May 13, 2024
c22fa6c
fix numbering
forrestfwilliams May 13, 2024
d75eca6
add ec2 language
forrestfwilliams May 13, 2024
f40b5f3
Merge pull request #21 from ASFHyP3/nvidia
forrestfwilliams May 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [PEP 440](https://www.python.org/dev/peps/pep-0440/)
and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.4.0]

### Added
* Support for GPU accelerated processing using CUDA.

## [0.3.0]

Expand Down
10 changes: 6 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ LABEL org.opencontainers.image.documentation="https://hyp3-docs.asf.alaska.edu"

ARG DEBIAN_FRONTEND=noninteractive

ENV USEGPU="false"

ENV PYTHONDONTWRITEBYTECODE=true
ENV PROC_HOME=/home/conda/back-projection
ENV MYHOME=/home/conda
Expand All @@ -36,9 +38,9 @@ RUN groupadd -g "${CONDA_GID}" --system conda && \
echo ". /opt/conda/etc/profile.d/conda.sh" >> /home/conda/.profile && \
echo "conda activate base" >> /home/conda/.profile

SHELL ["/bin/bash", "-l", "-c"]

USER ${CONDA_UID}
SHELL ["/bin/bash", "-l", "-c"]
WORKDIR /home/conda/

RUN curl -sL https://github.com/ASFHyP3/back-projection/archive/refs/tags/v${BACK_PROJECTION_TAG}.tar.gz > ./back-projection.tar.gz && \
Expand All @@ -47,10 +49,10 @@ RUN curl -sL https://github.com/ASFHyP3/back-projection/archive/refs/tags/v${BAC
rm ./back-projection.tar.gz && \
rm -rf ./back-projection/fft

COPY --chown=${CONDA_UID}:${CONDA_GID} ./scripts/build_proc_cpu.sh ./back-projection
COPY --chown=${CONDA_UID}:${CONDA_GID} ./scripts/build_proc.sh ./back-projection
RUN cd /home/conda/back-projection && \
chmod +x ./build_proc_cpu.sh && \
./build_proc_cpu.sh && \
chmod +x ./build_proc.sh && \
./build_proc.sh && \
find $PROC_HOME -type f -name "*.py" -exec chmod +x {} + && \
cd /home/conda/

Expand Down
86 changes: 86 additions & 0 deletions Dockerfile.gpu
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
FROM nvidia/cuda:12.4.1-devel-ubuntu20.04

# For opencontainers label definitions, see:
# https://github.com/opencontainers/image-spec/blob/master/annotations.md
LABEL org.opencontainers.image.title="HyP3 back-projection"
LABEL org.opencontainers.image.description="HyP3 plugin for back-projection processing"
LABEL org.opencontainers.image.vendor="Alaska Satellite Facility"
LABEL org.opencontainers.image.authors="ASF Tools Team <[email protected]>"
LABEL org.opencontainers.image.licenses="BSD-3-Clause"
LABEL org.opencontainers.image.url="https://github.com/ASFHyP3/hyp3-back-projection"
LABEL org.opencontainers.image.source="https://github.com/ASFHyP3/hyp3-back-projection"
LABEL org.opencontainers.image.documentation="https://hyp3-docs.asf.alaska.edu"

ARG DEBIAN_FRONTEND=noninteractive
ARG CONDA_UID=1000
ARG CONDA_GID=1000
ARG BACK_PROJECTION_TAG=0.2.0
ARG FFTW_TAG=3.3.9
ARG MINIFORGE_NAME=Miniforge3
ARG MINIFORGE_VERSION=24.3.0-0

# USEGPU environment variable used by build_proc.sh
ENV USEGPU="true"
ENV CONDA_DIR=/opt/conda
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
ENV PATH=${CONDA_DIR}/bin:${PATH}
ENV PYTHONDONTWRITEBYTECODE=true
ENV PROC_HOME=/home/conda/back-projection
ENV MYHOME=/home/conda

# Conda setup
RUN apt-get update > /dev/null && \
apt-get install --no-install-recommends --yes \
wget bzip2 ca-certificates \
git \
tini \
> /dev/null && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
wget --no-hsts --quiet https://github.com/conda-forge/miniforge/releases/download/${MINIFORGE_VERSION}/${MINIFORGE_NAME}-${MINIFORGE_VERSION}-Linux-$(uname -m).sh -O /tmp/miniforge.sh && \
/bin/bash /tmp/miniforge.sh -b -p ${CONDA_DIR} && \
rm /tmp/miniforge.sh && \
conda clean --tarballs --index-cache --packages --yes && \
find ${CONDA_DIR} -follow -type f -name '*.a' -delete && \
find ${CONDA_DIR} -follow -type f -name '*.pyc' -delete && \
conda clean --force-pkgs-dirs --all --yes && \
echo ". ${CONDA_DIR}/etc/profile.d/conda.sh && conda activate base" >> /etc/skel/.bashrc && \
echo ". ${CONDA_DIR}/etc/profile.d/conda.sh && conda activate base" >> ~/.bashrc

RUN apt-get update && apt-get install -y --no-install-recommends unzip vim curl build-essential gfortran libfftw3-dev && \
apt-get clean && rm -rf /var/lib/apt/lists/*

RUN groupadd -g "${CONDA_GID}" --system conda && \
useradd -l -u "${CONDA_UID}" -g "${CONDA_GID}" --system -d /home/conda -m -s /bin/bash conda && \
chown -R conda:conda /opt && \
echo ". /opt/conda/etc/profile.d/conda.sh" >> /home/conda/.profile && \
echo "conda activate base" >> /home/conda/.profile

SHELL ["/bin/bash", "-l", "-c"]

USER ${CONDA_UID}
WORKDIR /home/conda/

RUN curl -sL https://github.com/ASFHyP3/back-projection/archive/refs/tags/v${BACK_PROJECTION_TAG}.tar.gz > ./back-projection.tar.gz && \
mkdir -p ./back-projection && \
tar -xvf ./back-projection.tar.gz -C ./back-projection/ --strip=1 && \
rm ./back-projection.tar.gz && \
rm -rf ./back-projection/fft

COPY --chown=${CONDA_UID}:${CONDA_GID} ./scripts/build_proc.sh ./back-projection
RUN cd /home/conda/back-projection && \
chmod +x ./build_proc.sh && \
./build_proc.sh && \
find $PROC_HOME -type f -name "*.py" -exec chmod +x {} + && \
cd /home/conda/

COPY --chown=${CONDA_UID}:${CONDA_GID} . /hyp3-back-projection/

RUN mamba env create -f /hyp3-back-projection/environment.yml && \
conda clean -afy && \
conda activate hyp3-back-projection && \
sed -i 's/conda activate base/conda activate hyp3-back-projection/g' /home/conda/.profile && \
python -m pip install --no-cache-dir /hyp3-back-projection

ENTRYPOINT ["/hyp3-back-projection/src/hyp3_back_projection/etc/entrypoint.sh"]
CMD ["-h"]
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,36 @@ Your credentials can be passed to the workflows via command-line options (`--esa

If you haven't set up a `.netrc` file
before, check out this [guide](https://harmony.earthdata.nasa.gov/docs#getting-started) to get started.

## GPU Setup:
In order for Docker to be able to use the host's GPU, the host must have the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/index.html) installed and configured.
The process is different for different OS's and Linux distros. The setup process for the most common distros, including Ubuntu,
can be found [here](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#configuration). Make sure to follow the [Docker configuration steps](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#configuration) after installing the package.

### EC2 Setup
When running on an EC2 instance, the following setup is recommended:
1. Create a [P3-family EC2 instance](https://aws.amazon.com/ec2/instance-types/p3/) with the [Amazon Linux 2 AMI with NVIDIA TESLA GPU Driver](https://aws.amazon.com/marketplace/pp/prodview-64e4rx3h733ru?sr=0-4&ref_=beagle&applicationId=AWSMPContessa)
2. Install Docker and the nvidia-container-toolkit on the EC2 instance:
```bash
sudo yum-config-manager --disable amzn2-graphics
curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
sudo yum install docker -y
sudo yum install nvidia-container-toolkit -y
sudo yum-config-manager --enable amzn2-graphics
```
3. Optionally, set up Docker to not require `sudo` and to start when the EC2 instance starts
```bash
sudo systemctl start docker && \
sudo usermod -a -G docker ec2-user && \
sudo systemctl enable docker
```
4. Exit the EC2 instance and re-enter
5. To test the GPU setup, run the base NVIDIA container:
```bash
docker run -it --gpus all nvidia/cuda:12.4.1-devel-ubuntu20.04 nvidia-smi
```
6. Build the actual container and run it:
```bash
docker build -t back-projection:gpu -f Dockerfile.gpu .
docker run --gpus=all --rm -it back-projection:gpu ++process back_projection --help
```
25 changes: 14 additions & 11 deletions scripts/build_proc_cpu.sh → scripts/build_proc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
MULTIARCH_DIR=/usr/lib/$(gcc -print-multiarch)
FFTW_LIB=$MULTIARCH_DIR/libfftw3f.a
echo 'using FFTW library:' $FFTW_LIB
if [[ "$USEGPU" == "true" ]]; then
echo 'building with GPU support'
fi

# Works
cd DEM
gfortran -o mosaicDEM mosaicDEM.f90
gfortran -o createspecialdem createspecialdem.f90
Expand All @@ -19,9 +21,10 @@ gfortran -c processsubcpu.f90 backprojectcpusub.f90 bounds.f90 orbitrangetime.f9
gcc -o sentinel_raw_process_cpu sentinel_raw_process_cpu.o decode_line_memory.o processsubcpu.o backprojectcpusub.o azimuth_compress_cpu.o bounds.o orbitrangetime.o latlon.o intp_orbit.o radar_to_xyz.o unitvec.o tcnbasis.o curvature.o cross.o orbithermite.o filelen.o io.o sentineltimingsub.o getburststatevectors.o $FFTW_LIB -lgfortran -lgomp -lm -lrt -lpthread
echo 'built sentinel_raw_process_cpu'

# nvcc -o howmanygpus howmanygpus.cu
#
# echo 'built howmanygpus'
if [[ "$USEGPU" == "true" ]]; then
nvcc -o howmanygpus howmanygpus.cu
echo 'built howmanygpus'
fi

cd geo2rdr
gfortran -o estimatebaseline estimatebaseline.f90 intp_orbit.f90 latlon.f90 orbithermite.f -ffixed-line-length-none
Expand Down Expand Up @@ -80,20 +83,20 @@ cd ..

echo 'built snaphu'

# nvcc -o gpu_arch gpu_arch.cu
# echo 'built gpu architecture probe'
#
# ./gpu_arch | cat > GPU_ARCH; source ./GPU_ARCH; rm GPU_ARCH

cd sentinel

gcc -c filelen.c io.c sentinel_raw_process.c decode_line_memory.c -lm -fopenmp

echo 'built raw_process components in sentinel'

# nvcc -gencode arch=compute_$GPU_ARCH,code=sm_$GPU_ARCH -c azimuth_compress.cu -Wno-deprecated-gpu-targets
if [[ "$USEGPU" == "true" ]]; then
nvcc -gencode arch=compute_89,code=sm_89 -c azimuth_compress.cu -Wno-deprecated-gpu-targets
fi

gfortran -c processsub.f90 backprojectgpusub.f90 bounds.f90 orbitrangetime.f90 latlon.f90 intp_orbit.f90 radar_to_xyz.f90 unitvec.f90 tcnbasis.f90 curvature.f90 cross.f90 orbithermite.f sentineltimingsub.f90 getburststatevectors.f90 -ffixed-line-length-none -fopenmp

# nvcc -o sentinel_raw_process sentinel_raw_process.o decode_line_memory.o processsub.o backprojectgpusub.o azimuth_compress.o bounds.o orbitrangetime.o latlon.o intp_orbit.o radar_to_xyz.o unitvec.o tcnbasis.o curvature.o cross.o orbithermite.o filelen.o io.o sentineltimingsub.o getburststatevectors.o $FFTW_LIB -lstdc++ -lgfortran -lgomp
if [[ "$USEGPU" == "true" ]]; then
nvcc -o sentinel_raw_process sentinel_raw_process.o decode_line_memory.o processsub.o backprojectgpusub.o azimuth_compress.o bounds.o orbitrangetime.o latlon.o intp_orbit.o radar_to_xyz.o unitvec.o tcnbasis.o curvature.o cross.o orbithermite.o filelen.o io.o sentineltimingsub.o getburststatevectors.o $FFTW_LIB -lstdc++ -lgfortran -lgomp
fi

cd ..
53 changes: 35 additions & 18 deletions src/hyp3_back_projection/back_projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import argparse
import logging
import os
import zipfile
from pathlib import Path
from typing import Iterable, Optional
Expand All @@ -30,26 +31,40 @@ def create_param_file(dem_path: Path, dem_rsc_path: Path, output_dir: Path):
f.write('\n'.join(lines))


def back_project_single_granule(granule_path: Path, orbit_path: Path, work_dir: Path) -> None:
"""Back-project a single Sentinel-1 level-0 granule.
Args:
granule_path: Path to the granule to back-project
orbit_path: Path to the orbit file for the granule
"""
required_files = ['elevation.dem', 'elevation.dem.rsc', 'params']
def check_required_files(required_files: Iterable, work_dir: Path) -> None:
for file in required_files:
if not (work_dir / file).exists():
raise FileNotFoundError(f'Missing required file: {file}')

args = [str(granule_path.with_suffix('')), str(orbit_path)]
utils.call_stanford_module('sentinel/sentinel_scene_cpu.py', args, work_dir=work_dir)

def clean_up_after_back_projection(work_dir: Path) -> None:
patterns = ['*hgt*', 'dem*', 'DEM*', 'q*', '*positionburst*']
for pattern in patterns:
[f.unlink() for f in work_dir.glob(pattern)]


def create_product(work_dir):
def back_project_granules(granule_orbit_pairs: Iterable, work_dir: Path, gpu: bool = False) -> None:
"""Back-project a set of Sentinel-1 level-0 granules using the CPU-based workflow.
Args:
granule_orbit_pairs: List of tuples of granule and orbit file paths
work_dir: Working directory for processing
"""
check_required_files(['elevation.dem', 'elevation.dem.rsc', 'params'], work_dir)

if gpu:
os.environ['CUDA_DEVICE_ORDER'] = 'PCI_BUS_ID'
os.environ['CUDA_VISIBLE_DEVICES'] = '0'

cmd = 'sentinel/sentinel_scene_multigpu.py' if gpu else 'sentinel/sentinel_scene_cpu.py'
for granule_path, orbit_path in granule_orbit_pairs:
args = [str(granule_path.with_suffix('')), str(orbit_path)]
utils.call_stanford_module(cmd, args, work_dir=work_dir)

clean_up_after_back_projection(work_dir)


def create_product(work_dir) -> Path:
"""Create a product zip file.
Includes files needed for further processing (gslc, orbit, and parameter file).
Expand Down Expand Up @@ -88,7 +103,8 @@ def back_project(
bucket: str = None,
bucket_prefix: str = '',
work_dir: Optional[Path] = None,
) -> Path:
gpu: bool = False,
):
"""Back-project a set of Sentinel-1 level-0 granules.
Args:
Expand All @@ -100,6 +116,7 @@ def back_project(
bucket: AWS S3 bucket for uploading the final product(s)
bucket_prefix: Add a bucket prefix to the product(s)
work_dir: Working directory for processing
gpu: Use the GPU-based version of the workflow
"""
utils.set_creds('EARTHDATA', earthdata_username, earthdata_password)
utils.set_creds('ESA', esa_username, esa_password)
Expand All @@ -108,27 +125,26 @@ def back_project(

print('Downloading data...')
bboxs = []
back_project_args = []
granule_orbit_pairs = []
for granule in granules:
granule_path, granule_bbox = utils.download_raw_granule(granule, work_dir)
granule_path, granule_bbox = utils.download_raw_granule(granule, work_dir, unzip=True)
orbit_path = utils.download_orbit(granule, work_dir)
bboxs.append(granule_bbox)
back_project_args.append((granule_path, orbit_path))
granule_orbit_pairs.append((granule_path, orbit_path))

full_bbox = unary_union(bboxs).buffer(0.1)
dem_path = dem.download_dem_for_back_projection(full_bbox, work_dir)
create_param_file(dem_path, dem_path.with_suffix('.dem.rsc'), work_dir)

for granule_path, orbit_path in back_project_args:
back_project_single_granule(granule_path, orbit_path, work_dir=work_dir)
back_project_granules(granule_orbit_pairs, work_dir=work_dir, gpu=gpu)

utils.call_stanford_module('util/merge_slcs.py', work_dir=work_dir)

if bucket:
zip_path = create_product(work_dir)
upload_file_to_s3(zip_path, bucket, bucket_prefix)

print(f'Finish back-projection for {list(work_dir.glob("S1*.geo"))[0].with_suffix("").name}!')
print(f'Finished back-projection for {list(work_dir.glob("S1*.geo"))[0].with_suffix("").name}!')


def main():
Expand All @@ -146,6 +162,7 @@ def main():
parser.add_argument('--esa-password', default=None, help="Password for ESA's Copernicus Data Space Ecosystem")
parser.add_argument('--bucket', help='AWS S3 bucket HyP3 for upload the final product(s)')
parser.add_argument('--bucket-prefix', default='', help='Add a bucket prefix to product(s)')
parser.add_argument('--gpu', default=False, action='store_true', help='Use the GPU-based version of the workflow.')
parser.add_argument('granules', nargs='+', help='Level-0 S1 granule to back-project.')
args = parser.parse_args()

Expand Down
Loading
Loading