Skip to content

Commit

Permalink
Add 0382/WignerSymbol to the benchmarks and re-run everything
Browse files Browse the repository at this point in the history
  • Loading branch information
Luthaf committed Sep 1, 2023
1 parent eee1ad3 commit ab76b97
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ bench = false
lazy_static = "1"
smallvec = "1"
parking_lot = "0.12"
lru = "0.10"
lru = "0.11"
rayon = "1"
num-bigint = "0.4"
num-traits = "0.2"
Expand Down
37 changes: 25 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,23 @@ for j1 in range(max_angular):
elapsed = start - time.now()
```

Here are the results on an Apple M1 Max (10 cores) CPU:
Here are the results on an Apple M1 Max (10 cores) CPU, against a handful of
other libraries:

| angular momentum | wigners (this) | wigner-symbols v0.5 | WignerSymbols.jl v2.0 | wigxjpf v1.11 | sympy v1.11 |
|------------------|----------------|---------------------|-----------------------|---------------|-------------|
| 4 | 0.190 ms | 7.50 ms | 2.58 ms | 0.228 ms | 28.7 ms |
| 8 | 4.46 ms | 227 ms | 47.0 ms | 7.36 ms | 1.36 s |
| 12 | 34.0 ms | 1.94 s | 434 ms | 66.2 ms | 23.1 s |
| 16 | 156 ms | 9.34 s | 1.98 s | 333 ms | / |
| 20 | 531 ms | / | 6.35 s | 1.21 s | / |
- wigner-symbols: https://crates.io/crates/wigner-symbols
- WignerSymbols.jl: https://github.com/Jutho/WignerSymbols.jl
- wigxjpf: http://fy.chalmers.se/subatom/wigxjpf/
- 0382/WignerSymbol: https://github.com/0382/WignerSymbol
- sympy: https://docs.sympy.org/latest/modules/physics/quantum/cg.html

| code & version | max_angular=4 | 8 | 12 | 16 | 20 |
|----------------------------|---------------|---------|---------|---------|--------|
| wigners (this) | 0.190 ms | 4.60 ms | 36.5 ms | 172 ms | 572 ms |
| wigner-symbols v0.5 | 6.00 ms | 181 ms | 1.53 s | 7.32 s | / |
| WignerSymbols.jl v2.0 | 1.09 ms | 21.1 ms | 179 ms | 902 ms | 3.09 s |
| wigxjpf v1.11 | 0.237 ms | 7.65 ms | 68.3 ms | 342 ms | 1.24 s |
| 0382/WignerSymbol vf8c8dce | 0.070 ms | 2.26 ms | 19.3 ms | 93.5 ms | 320 ms |
| sympy v1.11 | 24.8 ms | 1.15 s | 20.8 s | / | / |


A second set of benchmarks checks computing Wigner symbols for large `j`, with the
Expand All @@ -117,16 +125,21 @@ for m1 in range(-10, 10 + 1):
elapsed = start - time.now()
```

| code & version | j1=300, j2=100, j3=250 |
|----------------------------|-------------------------|
| wigners (this) | 29.2 ms |
| wigner-symbols v0.5 | 13.8 ms |
| WignerSymbols.jl v2.0 | 11.5 ms |
| wigxjpf v1.11 | 7.45 ms |
| 0382/WignerSymbol vf8c8dce | / (wrong result) |
| sympy v1.11 | 2.34 s |

| (j1, j2, j3) | wigners (this) | wigner-symbols v0.5 | WignerSymbols.jl v2.0 | wigxjpf v1.11 | sympy v1.11 |
|------------------|----------------|---------------------|-----------------------|---------------|-------------|
| (300, 100, 250) | 38.7 ms | 16.5 ms | 32.9 ms | 7.60 ms | 2.31 s |

To run the benchmarks yourself on your own machine, execute the following commands:

```bash
cd benchmarks
cargo bench # this gives the results for wigners, wigner-symbols and wigxjpf
cargo bench # this gives the results for wigners, wigner-symbols, wigxjpf and 0382/WignerSymbol

python sympy-bench.py # this gives the results for sympy

Expand Down
30 changes: 30 additions & 0 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,46 @@ cmake_minimum_required(VERSION 3.10)

project(wigner_benchmarks)

set(CMAKE_BUILD_TYPE "release" CACHE STRING "" FORCE)

include(ExternalProject)

ExternalProject_Add(wigxjpf
URL http://fy.chalmers.se/subatom/wigxjpf/wigxjpf-1.11.tar.gz
CONFIGURE_COMMAND ""
BUILD_COMMAND make -C ../wigxjpf/
INSTALL_COMMAND ""
DOWNLOAD_EXTRACT_TIMESTAMP ON
)

install(FILES
${CMAKE_CURRENT_BINARY_DIR}/wigxjpf-prefix/src/wigxjpf/lib/libwigxjpf.a
DESTINATION "lib"
)

file(DOWNLOAD
"https://raw.githubusercontent.com/0382/WignerSymbol/f8c8dce9ceefda20ac4ea57bf36304b418e8c0c0/WignerSymbolSingleton.hpp"
${CMAKE_CURRENT_BINARY_DIR}/WignerSymbolSingleton.hpp
)

add_library(wigner-symbol-0382 STATIC wigner-symbol-0382.cpp)
target_include_directories(wigner-symbol-0382 PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_compile_features(wigner-symbol-0382 PRIVATE cxx_std_17)
target_link_options(wigner-symbol-0382 PRIVATE -static-libc++)

install(TARGETS wigner-symbol-0382
DESTINATION "lib"
)


# Get default C++ libraries to link
file(WRITE ${PROJECT_BINARY_DIR}/cxx_link_libs.cmake "")
foreach(lib ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES})
file(APPEND ${PROJECT_BINARY_DIR}/cxx_link_libs.cmake "${lib}\n")
endforeach()

# Get default C++ search path for libraries
file(WRITE ${PROJECT_BINARY_DIR}/cxx_link_dirs.cmake "")
foreach(dir ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
file(APPEND ${PROJECT_BINARY_DIR}/cxx_link_dirs.cmake "${dir}\n")
endforeach()
6 changes: 5 additions & 1 deletion benchmarks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ publish = false
cmake = "0.1"

[dev-dependencies]
criterion = "0.4"
criterion = "0.5"
wigners = {path = ".."}
wigner-symbols = "0.5"

Expand All @@ -23,3 +23,7 @@ harness = false
[[bench]]
name = "wigxjpf"
harness = false

[[bench]]
name = "ws0382"
harness = false
3 changes: 3 additions & 0 deletions benchmarks/benches/wigners.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ fn bench_wigner3j(c: &mut Criterion) {
return duration
})
});

let v = wigners::wigner_3j(300, 100, 250, 0, 1, -1);
dbg!(v);
}

criterion_group!(wigner3j, bench_wigner3j);
Expand Down
71 changes: 71 additions & 0 deletions benchmarks/benches/ws0382.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#![allow(clippy::needless_return)]

use wigner_benchmarks::wigner_symbol_0382;

use criterion::{Criterion, criterion_group, criterion_main};

fn compute_all_wigner_3j(max_angular: i32) {
for l1 in 0..=max_angular {
for l2 in 0..=max_angular {
for l3 in 0..=max_angular {
for m1 in -l1..=l1 {
for m2 in -l2..=l2 {
for m3 in -l3..=l3 {
unsafe {
wigner_symbol_0382::ws0382_wigner_3j(
2 * l1, 2 * l2, 2 * l3,
2 * m1, 2 * m2, 2 * m3
);
}
}
}
}
}
}
}
}


fn compute_large_wigner_3j(l1: i32, l2: i32, l3: i32) {
for m1 in -10..=10 {
for m2 in -10..=10 {
for m3 in -10..=10 {
unsafe {
wigner_symbol_0382::ws0382_wigner_3j(
2 * l1, 2 * l2, 2 * l3,
2 * m1, 2 * m2, 2 * m3
);
}
}
}
}
}


fn bench_wigner3j(c: &mut Criterion) {
let mut group = c.benchmark_group("0382/WignerSymbol");
group.sample_size(10);
group.sampling_mode(criterion::SamplingMode::Flat);

unsafe {
wigner_symbol_0382::ws0382_init(600);
}

for &max_angular in &[4, 8, 12, 16, 20] {
group.bench_function(&format!("max_angular={}", max_angular), |b| {
b.iter(|| compute_all_wigner_3j(max_angular))
});
}

group.bench_function("j = (300, 100, 250)", |b| {
b.iter(|| compute_large_wigner_3j(300, 100, 250))
});

let v = unsafe {
wigner_symbol_0382::ws0382_wigner_3j(2 * 300, 2 * 100, 2 * 250, 0, 2, -2)
};
dbg!(v);
}

criterion_group!(wigner3j, bench_wigner3j);
criterion_main!(wigner3j);
42 changes: 42 additions & 0 deletions benchmarks/build.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,49 @@
use std::path::Path;
use std::fs::File;
use std::io::Read;


fn list_cxx_libs(build: &Path) {
let mut dirs_file = File::open(build.join("cxx_link_dirs.cmake")).unwrap();
let mut content = String::new();
dirs_file.read_to_string(&mut content).unwrap();
for dir in content.lines() {
println!("cargo:rustc-link-search=native={}", dir);
}

let mut libs_file = File::open(build.join("cxx_link_libs.cmake")).unwrap();
let mut content = String::new();
libs_file.read_to_string(&mut content).unwrap();
for lib in content.lines() {
if !is_excluded_lib(lib) {
println!("cargo:rustc-link-lib={}", lib);
}
}
}

#[cfg(target_os = "macos")]
fn is_excluded_lib(name: &str) -> bool {
// libclang_rt.osx.a is not found by the linker, and to_library is a bug
// with cmake (trying to parse -lto_library=<...>)
name.contains("libclang_rt.osx.a") || name == "to_library"
}

#[cfg(target_os = "linux")]
fn is_excluded_lib(name: &str) -> bool {
// Fiw warnings about redundant linker flag
name == "gcc" || name == "gcc_s"
}

#[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn is_excluded_lib(_: &str) -> bool {
false
}

fn main() {
let mut cmake = cmake::Config::new(".");
let out_dir = cmake.build();
let lib = out_dir.join("lib");
println!("cargo:rustc-link-search=native={}", lib.display());

list_cxx_libs(&out_dir.join("build"));
}
12 changes: 12 additions & 0 deletions benchmarks/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,15 @@ pub mod wigxjpf {
pub fn wig9jj(two_j1: c_int, two_j2: c_int, two_j3: c_int, two_j4: c_int, two_j5: c_int, two_j6: c_int, two_j7: c_int, two_j8: c_int, two_j9: c_int) -> c_double;
}
}


pub mod wigner_symbol_0382 {
use std::os::raw::{c_int, c_void, c_double};

#[link(name="wigner-symbol-0382", kind="static")]
extern "C" {
pub fn ws0382_init(l_max: c_int) -> c_void;

pub fn ws0382_wigner_3j(j1: c_int, j2: c_int, j3: c_int, m1: c_int, m2: c_int, m3: c_int) -> c_double;
}
}
10 changes: 10 additions & 0 deletions benchmarks/wigner-symbol-0382.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "WignerSymbolSingleton.hpp"


extern "C" void ws0382_init(int l_max) {
util::wigner_init(l_max, "Jmax", 3);
}

extern "C" double ws0382_wigner_3j(int two_j1, int two_j2, int two_j3, int two_m1, int two_m2, int two_m3) {
return util::wigner_3j(two_j1, two_j2, two_j3, two_m1, two_m2, two_m3);
}

0 comments on commit ab76b97

Please sign in to comment.