Skip to content

Commit

Permalink
Add coverage and bump version.
Browse files Browse the repository at this point in the history
Along with adding coverage to CI, add more tests to increase coverage.

Remove dependence on dashmap in favour of using parking_lot directly.
Dashmap could in rare cases cause a deadlock.

Improve the CUDA de-duplication code.

Use Rust 2021 edition.

Update dependency versions and adjust the code accordingly.

Rename the GitHub workflow file extensions.

Add a changelog.
  • Loading branch information
cjordan committed Jan 10, 2022
1 parent e78ff09 commit a55e44f
Show file tree
Hide file tree
Showing 21 changed files with 1,147 additions and 378 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ cp .github/workflows/releases-readme.md README.md
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
# I don't know why, but I need to reinstall Rust. Probably something to do with
# GitHub overriding env variables.
curl https://sh.rustup.rs -sSf | sh -s -- -y
curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal

# Build a release for each x86_64 microarchitecture level. v4 can't be
# compiled on GitHub for some reason.
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Based on https://github.com/actions-rs/meta/blob/master/recipes/quickstart.md

on: [push, pull_request]

name: Generate Coverage report

jobs:
coverage:
runs-on: ubuntu-latest
container: mwatelescope/birli:latest
environment: CI

steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Install nightly toolchain
run: |
curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal
export PATH="${HOME}/.cargo/bin:${PATH}"
rustup toolchain install nightly --component llvm-tools-preview
rustup default nightly
- name: Install system and Cargo Packages
run: |
export PATH="${HOME}/.cargo/bin:${PATH}"
apt-get update
apt-get install -y lcov clang curl zip unzip libssl-dev jq libhdf5-dev liberfa-dev
cargo update
cargo install --force cargo-make cargo-binutils grcov
env:
DEBIAN_FRONTEND: noninteractive

- name: Get the HDF5 file
run: curl http://ws.mwatelescope.org/static/mwa_full_embedded_element_pattern.h5 -o mwa_full_embedded_element_pattern.h5

- name: Generate test lcov coverage into coverage/ dir
env:
LD_LIBRARY_PATH: /usr/local/lib/
CARGO_INCREMENTAL: 0
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
RUSTDOCFLAGS: "-Cpanic=abort"
LLVM_PROFILE_FILE: json5format-%m.profraw
MWA_BEAM_FILE: mwa_full_embedded_element_pattern.h5
run: |
mkdir -p coverage
export PATH="${HOME}/.cargo/bin:${PATH}"
cargo build
cargo test
zip -0 ccov.zip `find . \( -name "mwa_hyperbeam*.gc*" \) -print`
grcov ccov.zip -s . -t lcov --llvm --branch --ignore-not-existing --ignore "/*" --ignore src/jones_test.rs --excl-br-line "^.*((debug_)?assert(_eq|_ne|_abs_diff_(eq|ne))?!|#\[derive\()" -o coverage/coverage.lcov
- name: Upload reports to codecov.io
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_TOKEN }}
File renamed without changes.
File renamed without changes.
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic
Versioning](https://semver.org/spec/v2.0.0.html).

## [0.4.0] - 2021-10-14
### Added
- FEE beam code for CUDA
- The original code is courtesy of Cristian Di Pietrantonio and Maciej
Cytowski on behalf of the Pawsey Supercomputing Centre.
- CHJ modified it to be easily called from Rust.
- It is is possible to run the code in single- or double-precision (Cargo
features "cuda-single" and "cuda", respectively). This is important because
most NVIDIA desktop GPUs have significantly less double-precision compute
capability.
- There are examples of using the CUDA functionality from Rust, C and Python.
- Parallactic angle correction
- Jack Line did a thorough investigation of what our beam responses should be;
the write up is
[here](https://github.com/JLBLine/polarisation_tests_for_FEE).
- New Rust functions are provided (`*_eng*` for "engineering") to get the
old-style beam responses. The existing functions do the corrections by
default.
- A binary `verify-beam-file`
- (In theory) verifies that an HDF5 FEE beam file has sensible contents.
- The only way that standard beam calculations can fail is if the spherical
harmonic coefficients are nonsensical, so this binary is an attempt to
ensure that the files used are sensible.

### Changed
- Rust API
- `calc_jones*_array` functions now return a `Vec`, not an `Array1`.
- Rust internals
- Small optimisations.
- Small documentation clean ups.
- C API
- The caller must now specify if they want the parallactic angle correction.
- All functions that can fail return an error code. If this is non-zero, the
function failed.
- The caller can also provide error strings to these fallible functions; in
the event of failure, an error message is written to the string.
- The example C files have been modified to conform with these changes.
- Python API
- The caller must now specify if they want the parallactic angle correction.
27 changes: 17 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
[package]
name = "mwa_hyperbeam"
version = "0.3.4"
version = "0.4.0"
authors = ["Christopher H. Jordan <[email protected]>",
"Jack L. B. Line <[email protected]>",
"Marcin Sokolowski <[email protected]>"]
edition = "2018"
edition = "2021"
rust-version = "1.56"
license = "MPL-2.0"
readme = "README.md"
description = "Primary beam code for the Murchison Widefield Array (MWA) radio telescope."
Expand All @@ -30,28 +31,33 @@ cuda = ["marlu/cuda", "cc"]
# Opt-out of double precision, use only single precision.
cuda-single = ["cuda"]

# Example-only dependencies
examples = ["anyhow", "clap"]

[profile.release]
lto = true
codegen-units = 1 # Set this to 1 in Cargo.toml to allow for maximum size reduction optimizations

[dependencies]
cfg-if = "1.0.*"
dashmap = "4.0.*"
hdf5 = "0.7.*"
hdf5 = "0.8.*"
marlu = { version = "0.3.*", default-features = false }
parking_lot = "0.11.*"
thiserror = "1.0.*"

hdf5-sys = { version = "0.7.*", features = ["static", "threadsafe"], optional = true }
hdf5-sys = { version = "0.8.*", features = ["static", "threadsafe"], optional = true }

pyo3 = { version = "0.15.*", features = ["extension-module"], optional = true }
numpy = { version = "0.15.*", optional = true }

pyo3 = { version = "0.13.*", features = ["extension-module"], optional = true }
numpy = { version = "0.13.0", optional = true }
# Example-only dependencies.
anyhow = { version = "1.0.*", optional = true }
clap = { version = "3.0.*", features = ["derive"], optional = true }

[dev-dependencies]
anyhow = "1.0.*"
approx = { version = "0.5.*", features = ["num-complex"] }
criterion = "0.3.*"
serial_test = "0.5.*"
structopt = "0.3.*"

ndarray = { version = ">=0.15.4,<0.16", features = ["approx-0_5"] }

Expand All @@ -75,7 +81,8 @@ harness = false

[[example]]
name = "beam_calcs"
required-features = ["examples"]

[[example]]
name = "beam_calcs_cuda"
required-features = ["cuda"]
required-features = ["examples", "cuda"]
42 changes: 35 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
<div class="bg-gray-dark" align="center" style="background-color:#24292e">
<img src="hyperbeam.png" height="200px" alt="hyperbeam logo">
<br/>
<a href="https://docs.rs/crate/mwa_hyperbeam"><img src="https://docs.rs/mwa_hyperbeam/badge.svg" alt="docs"></a>
<img src="https://github.com/MWATelescope/mwa_hyperbeam/workflows/Cross-platform%20tests/badge.svg" alt="Cross-platform%20tests">
<a href="https://crates.io/crates/mwa_hyperbeam">
<img src="https://img.shields.io/crates/v/mwa_hyperbeam?logo=rust" alt="crates.io"></a>
<a href="https://docs.rs/crate/mwa_hyperbeam">
<img src="https://img.shields.io/docsrs/mwa_hyperbeam?logo=rust" alt="docs.rs"></a>
<img src="https://img.shields.io/github/workflow/status/MWATelescope/mwa_hyperbeam/Cross-platform%20tests?label=Cross-platform%20tests&logo=github" alt="Cross-platform%20tests">
<a href="https://codecov.io/gh/MWATelescope/mwa_hyperbeam">
<img src="https://codecov.io/gh/MWATelescope/mwa_hyperbeam/branch/main/graph/badge.svg?token=61JYU54DG2"/></a>
</div>

Primary beam code for the Murchison Widefield Array (MWA) radio telescope.
Expand All @@ -16,6 +21,10 @@ Full Embedded Element (FEE) primary beam model of the MWA, a.k.a. "the 2016
beam". This code should be used over all others. If there are soundness issues,
please raise them here so everyone can benefit.

See the
[changelog](https://github.com/MWATelescope/mwa_hyperbeam/blob/main/CHANGELOG.md)
for the latest changes to the code.

## Usage
`hyperbeam` requires the MWA FEE HDF5 file. This can be obtained with:

Expand Down Expand Up @@ -48,9 +57,8 @@ other words, most languages. See Rust, C and Python examples of usage in the

### CUDA
`hyperbeam` also can also be run on NVIDIA GPUs. To see an example of usage, see
any of the examples with "_cuda" in the name. CUDA functionality is only
provided with one of two Cargo features; see installing from source instructions
below.
any of the examples with "cuda" in the name. CUDA functionality is only provided
with one of two Cargo features; see installing from source instructions below.

## Installation
### Python PyPI
Expand All @@ -76,10 +84,10 @@ their respective licenses are also distributed.

`https://www.rust-lang.org/tools/install`

The Rust compiler must be at least version 1.47.0:
The Rust compiler must be at least version 1.56.0:
```bash
$ rustc -V
rustc 1.47.0 (18bf6b4f0 2020-10-07)
rustc 1.57.0 (f1edd0429 2021-11-29)
```

- [hdf5](https://www.hdfgroup.org/hdf5)
Expand Down Expand Up @@ -108,6 +116,26 @@ For usage with other languages, an include file will be in the `include`
directory, along with C-compatible shared and static objects in the
`target/release` directory.

#### CUDA
Are you running `hyperbeam` on a desktop NVIDIA GPU? Then you probably want to
compile with single-precision floats:

cargo build --release --features=cuda-single

Otherwise, go ahead with double-precision floats:

cargo build --release --features=cuda

Desktop GPUs (e.g. NVIDIA GeForce RTX 2070) have significantly less
double-precision compute capability than "data center" GPUs (e.g. NVIDIA V100).
Allowing `hyperbeam` to switch on the float type allows the user to decide
between the performance and precision compromise.

`CUDA` can also be linked statically (although it seems to link statically by
default regardless of this flag):

cargo build --release --features=cuda,cuda-static

#### Static dependencies
To make `hyperbeam` without a dependence on a system `HDF5` library, give the
`build` command a feature flag:
Expand Down
40 changes: 20 additions & 20 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ fn fee(c: &mut Criterion) {
let za = 80.0_f64.to_radians();
let freq = 51200000;
let delays = [0; 16];
let gains = [1.0; 16];
let amps = [1.0; 16];
let norm_to_zenith = false;
b.iter(|| {
let beam = FEEBeam::new("mwa_full_embedded_element_pattern.h5").unwrap();
beam.calc_jones(az, za, freq, &delays, &gains, norm_to_zenith)
beam.calc_jones(az, za, freq, &delays, &amps, norm_to_zenith)
.unwrap();
})
});
Expand All @@ -38,11 +38,11 @@ fn fee(c: &mut Criterion) {
let za = 80.0_f64.to_radians();
let freq = 51200000;
let delays = [0; 16];
let gains = [1.0; 16];
let amps = [1.0; 16];
let norm_to_zenith = false;
let beam = FEEBeam::new("mwa_full_embedded_element_pattern.h5").unwrap();
b.iter(|| {
beam.calc_jones(az, za, freq, &delays, &gains, norm_to_zenith)
beam.calc_jones(az, za, freq, &delays, &amps, norm_to_zenith)
.unwrap();
beam.empty_cache();
})
Expand All @@ -53,14 +53,14 @@ fn fee(c: &mut Criterion) {
let za = 80.0_f64.to_radians();
let freq = 51200000;
let delays = [0; 16];
let gains = [1.0; 16];
let amps = [1.0; 16];
let norm_to_zenith = false;
let beam = FEEBeam::new("mwa_full_embedded_element_pattern.h5").unwrap();
// Prime the cache.
beam.calc_jones(az, za, freq, &delays, &gains, norm_to_zenith)
beam.calc_jones(az, za, freq, &delays, &amps, norm_to_zenith)
.unwrap();
b.iter(|| {
beam.calc_jones(az, za, freq, &delays, &gains, norm_to_zenith)
beam.calc_jones(az, za, freq, &delays, &amps, norm_to_zenith)
.unwrap();
})
});
Expand All @@ -75,14 +75,14 @@ fn fee(c: &mut Criterion) {
}
let freq = 51200000;
let delays = [0; 16];
let gains = [1.0; 16];
let amps = [1.0; 16];
let norm_to_zenith = false;
let beam = FEEBeam::new("mwa_full_embedded_element_pattern.h5").unwrap();
// Prime the cache.
beam.calc_jones(az[0], za[0], freq, &delays, &gains, norm_to_zenith)
beam.calc_jones(az[0], za[0], freq, &delays, &amps, norm_to_zenith)
.unwrap();
b.iter(|| {
beam.calc_jones_array(&az, &za, freq, &delays, &gains, norm_to_zenith)
beam.calc_jones_array(&az, &za, freq, &delays, &amps, norm_to_zenith)
.unwrap();
})
});
Expand All @@ -99,17 +99,17 @@ fn fee(c: &mut Criterion) {
}
let freq = 51200000;
let delays = [0; 16];
let gains = [1.0; 16];
let amps = [1.0; 16];
let norm_to_zenith = false;
let beam = FEEBeam::new("mwa_full_embedded_element_pattern.h5").unwrap();
// Prime the cache.
beam.calc_jones(az[0], za[0], freq, &delays, &gains, norm_to_zenith)
beam.calc_jones(az[0], za[0], freq, &delays, &amps, norm_to_zenith)
.unwrap();
b.iter(|| {
az.par_iter()
.zip(za.par_iter())
.map(|(&a, &z)| {
beam.calc_jones(a, z, freq, &delays, &gains, norm_to_zenith)
beam.calc_jones(a, z, freq, &delays, &amps, norm_to_zenith)
.unwrap()
})
.collect::<Vec<_>>();
Expand Down Expand Up @@ -217,24 +217,24 @@ fn fee(c: &mut Criterion) {
// c.bench_function("calculating coefficients", |b| {
// let freq = 51200000;
// let delays = [0; 16];
// let gains = [1.0; 16];
// let amps = [1.0; 32];
// let beam = FEEBeam::new("mwa_full_embedded_element_pattern.h5").unwrap();
// b.iter(|| {
// let beam = FEEBeam::new("mwa_full_embedded_element_pattern.h5").unwrap();
// beam.populate_modes(freq, &delays, &gains).unwrap();
// beam.calc_modes(freq, &delays, &amps).unwrap();
// })
// });

// c.bench_function("getting coefficients from cache", |b| {
// let freq = 51200000;
// let delays = [0; 16];
// let gains = [1.0; 16];
// // Prime the cache.
// let amps = [1.0; 32];
// let beam = FEEBeam::new("mwa_full_embedded_element_pattern.h5").unwrap();
// beam.populate_modes(freq, &delays, &gains).unwrap();
// // Prime the cache.
// let _ = beam.get_modes(freq, &delays, &amps).unwrap();
// b.iter(|| {
// // By calling populate_modes before the loop we are benchmarking a
// // hot cache.
// beam.populate_modes(freq, &delays, &gains).unwrap();
// let _ = beam.get_modes(freq, &delays, &amps).unwrap();
// })
// });
}
Expand Down
Loading

0 comments on commit a55e44f

Please sign in to comment.