Skip to content
Snippets Groups Projects
Commit 5f96afc7 authored by Russel Arbore's avatar Russel Arbore
Browse files

cfd bench

parent b4e9f258
No related branches found
No related tags found
1 merge request!200Rodinia benches
Pipeline #201874 passed
...@@ -1297,6 +1297,7 @@ version = "0.1.0" ...@@ -1297,6 +1297,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"async-std", "async-std",
"clap", "clap",
"criterion",
"hercules_rt", "hercules_rt",
"juno_build", "juno_build",
"nom 8.0.0", "nom 8.0.0",
......
...@@ -8,6 +8,9 @@ edition = "2021" ...@@ -8,6 +8,9 @@ edition = "2021"
name = "juno_cfd" name = "juno_cfd"
path = "src/main.rs" path = "src/main.rs"
[lib]
path = "src/lib.rs"
[features] [features]
cuda = ["juno_build/cuda", "hercules_rt/cuda"] cuda = ["juno_build/cuda", "hercules_rt/cuda"]
...@@ -21,3 +24,10 @@ async-std = "*" ...@@ -21,3 +24,10 @@ async-std = "*"
clap = { version = "*", features = ["derive"] } clap = { version = "*", features = ["derive"] }
with_builtin_macros = "0.1.0" with_builtin_macros = "0.1.0"
nom = "*" nom = "*"
[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }
[[bench]]
name = "cfd_bench"
harness = false
#![feature(concat_idents)]
use criterion::{criterion_group, criterion_main, Criterion};
use hercules_rt::{runner, HerculesImmBox, HerculesImmBoxTo, HerculesMutBox, HerculesMutBoxTo};
juno_build::juno!("euler");
juno_build::juno!("pre_euler");
use juno_cfd::*;
fn cfd_bench(c: &mut Criterion) {
let mut group = c.benchmark_group("cfd bench");
let mut r = runner!(euler);
let data_file = "data/fvcorr.domn.097K".to_string();
let iterations = 1;
let block_size = 16;
let FarFieldConditions {
ff_variable,
ff_fc_momentum_x,
ff_fc_momentum_y,
ff_fc_momentum_z,
ff_fc_density_energy,
} = set_far_field_conditions();
let GeometryData {
nelr,
areas,
elements_surrounding_elements,
normals,
} = read_domain_geometry(data_file, block_size);
let mut variables = initialize_variables(nelr, ff_variable.as_slice());
let mut variables = HerculesMutBox::from(variables.as_mut_slice());
let areas = HerculesImmBox::from(areas.as_slice());
let elements_surrounding_elements =
HerculesImmBox::from(elements_surrounding_elements.as_slice());
let normals = HerculesImmBox::from(normals.as_slice());
let ff_variable = HerculesImmBox::from(ff_variable.as_slice());
let ff_fc_density_energy = vec![
ff_fc_density_energy.x,
ff_fc_density_energy.y,
ff_fc_density_energy.z,
];
let ff_fc_density_energy = HerculesImmBox::from(ff_fc_density_energy.as_slice());
let ff_fc_momentum_x = vec![ff_fc_momentum_x.x, ff_fc_momentum_x.y, ff_fc_momentum_x.z];
let ff_fc_momentum_x = HerculesImmBox::from(ff_fc_momentum_x.as_slice());
let ff_fc_momentum_y = vec![ff_fc_momentum_y.x, ff_fc_momentum_y.y, ff_fc_momentum_y.z];
let ff_fc_momentum_y = HerculesImmBox::from(ff_fc_momentum_y.as_slice());
let ff_fc_momentum_z = vec![ff_fc_momentum_z.x, ff_fc_momentum_z.y, ff_fc_momentum_z.z];
let ff_fc_momentum_z = HerculesImmBox::from(ff_fc_momentum_z.as_slice());
group.bench_function("cfd bench euler", |b| {
b.iter(|| {
async_std::task::block_on(async {
r.run(
nelr as u64,
iterations as u64,
variables.to(),
areas.to(),
elements_surrounding_elements.to(),
normals.to(),
ff_variable.to(),
ff_fc_density_energy.to(),
ff_fc_momentum_x.to(),
ff_fc_momentum_y.to(),
ff_fc_momentum_z.to(),
)
.await
});
})
});
let mut r = runner!(pre_euler);
let data_file = "data/fvcorr.domn.097K".to_string();
let iterations = 1;
let block_size = 16;
let FarFieldConditions {
ff_variable,
ff_fc_momentum_x,
ff_fc_momentum_y,
ff_fc_momentum_z,
ff_fc_density_energy,
} = set_far_field_conditions();
let GeometryData {
nelr,
areas,
elements_surrounding_elements,
normals,
} = read_domain_geometry(data_file, block_size);
let mut variables = initialize_variables(nelr, ff_variable.as_slice());
let mut variables = HerculesMutBox::from(variables.as_mut_slice());
let areas = HerculesImmBox::from(areas.as_slice());
let elements_surrounding_elements =
HerculesImmBox::from(elements_surrounding_elements.as_slice());
let normals = HerculesImmBox::from(normals.as_slice());
let ff_variable = HerculesImmBox::from(ff_variable.as_slice());
let ff_fc_density_energy = vec![
ff_fc_density_energy.x,
ff_fc_density_energy.y,
ff_fc_density_energy.z,
];
let ff_fc_density_energy = HerculesImmBox::from(ff_fc_density_energy.as_slice());
let ff_fc_momentum_x = vec![ff_fc_momentum_x.x, ff_fc_momentum_x.y, ff_fc_momentum_x.z];
let ff_fc_momentum_x = HerculesImmBox::from(ff_fc_momentum_x.as_slice());
let ff_fc_momentum_y = vec![ff_fc_momentum_y.x, ff_fc_momentum_y.y, ff_fc_momentum_y.z];
let ff_fc_momentum_y = HerculesImmBox::from(ff_fc_momentum_y.as_slice());
let ff_fc_momentum_z = vec![ff_fc_momentum_z.x, ff_fc_momentum_z.y, ff_fc_momentum_z.z];
let ff_fc_momentum_z = HerculesImmBox::from(ff_fc_momentum_z.as_slice());
group.bench_function("cfd bench pre-euler", |b| {
b.iter(|| {
async_std::task::block_on(async {
r.run(
nelr as u64,
iterations as u64,
variables.to(),
areas.to(),
elements_surrounding_elements.to(),
normals.to(),
ff_variable.to(),
ff_fc_density_energy.to(),
ff_fc_momentum_x.to(),
ff_fc_momentum_y.to(),
ff_fc_momentum_z.to(),
)
.await
});
})
});
}
criterion_group!(benches, cfd_bench);
criterion_main!(benches);
#![feature(concat_idents)]
mod rust_cfd;
mod setup;
use clap::Parser;
pub use crate::setup::*;
use hercules_rt::{runner, HerculesImmBox, HerculesImmBoxTo, HerculesMutBox, HerculesMutBoxTo};
juno_build::juno!("euler");
juno_build::juno!("pre_euler");
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
pub struct CFDInputs {
pub data_file: String,
pub iterations: usize,
pub block_size: usize,
#[clap(short = None, long = Some("pre-euler"))]
pub pre_euler: bool,
}
fn run_euler(
nelr: usize,
iterations: usize,
mut variables: AlignedSlice<f32>,
areas: &[f32],
elements_surrounding_elements: &[i32],
normals: &[f32],
ff_variable: &[f32],
ff_fc_density_energy: &Float3,
ff_fc_momentum_x: &Float3,
ff_fc_momentum_y: &Float3,
ff_fc_momentum_z: &Float3,
) -> Vec<f32> {
let mut variables = HerculesMutBox::from(variables.as_mut_slice());
let areas = HerculesImmBox::from(areas);
let elements_surrounding_elements = HerculesImmBox::from(elements_surrounding_elements);
let normals = HerculesImmBox::from(normals);
let ff_variable = HerculesImmBox::from(ff_variable);
// TODO: Make hercules box handle structs, for now we'll copy into a vec
let ff_fc_density_energy = vec![
ff_fc_density_energy.x,
ff_fc_density_energy.y,
ff_fc_density_energy.z,
];
let ff_fc_density_energy = HerculesImmBox::from(ff_fc_density_energy.as_slice());
let ff_fc_momentum_x = vec![ff_fc_momentum_x.x, ff_fc_momentum_x.y, ff_fc_momentum_x.z];
let ff_fc_momentum_x = HerculesImmBox::from(ff_fc_momentum_x.as_slice());
let ff_fc_momentum_y = vec![ff_fc_momentum_y.x, ff_fc_momentum_y.y, ff_fc_momentum_y.z];
let ff_fc_momentum_y = HerculesImmBox::from(ff_fc_momentum_y.as_slice());
let ff_fc_momentum_z = vec![ff_fc_momentum_z.x, ff_fc_momentum_z.y, ff_fc_momentum_z.z];
let ff_fc_momentum_z = HerculesImmBox::from(ff_fc_momentum_z.as_slice());
let mut runner = runner!(euler);
HerculesMutBox::from(async_std::task::block_on(async {
runner
.run(
nelr as u64,
iterations as u64,
variables.to(),
areas.to(),
elements_surrounding_elements.to(),
normals.to(),
ff_variable.to(),
ff_fc_density_energy.to(),
ff_fc_momentum_x.to(),
ff_fc_momentum_y.to(),
ff_fc_momentum_z.to(),
)
.await
}))
.as_slice()
.to_vec()
}
fn run_pre_euler(
nelr: usize,
iterations: usize,
mut variables: AlignedSlice<f32>,
areas: &[f32],
elements_surrounding_elements: &[i32],
normals: &[f32],
ff_variable: &[f32],
ff_fc_density_energy: &Float3,
ff_fc_momentum_x: &Float3,
ff_fc_momentum_y: &Float3,
ff_fc_momentum_z: &Float3,
) -> Vec<f32> {
let mut variables = HerculesMutBox::from(variables.as_mut_slice());
let areas = HerculesImmBox::from(areas);
let elements_surrounding_elements = HerculesImmBox::from(elements_surrounding_elements);
let normals = HerculesImmBox::from(normals);
let ff_variable = HerculesImmBox::from(ff_variable);
// TODO: Make hercules box handle structs, for now we'll copy into a vec
let ff_fc_density_energy = vec![
ff_fc_density_energy.x,
ff_fc_density_energy.y,
ff_fc_density_energy.z,
];
let ff_fc_density_energy = HerculesImmBox::from(ff_fc_density_energy.as_slice());
let ff_fc_momentum_x = vec![ff_fc_momentum_x.x, ff_fc_momentum_x.y, ff_fc_momentum_x.z];
let ff_fc_momentum_x = HerculesImmBox::from(ff_fc_momentum_x.as_slice());
let ff_fc_momentum_y = vec![ff_fc_momentum_y.x, ff_fc_momentum_y.y, ff_fc_momentum_y.z];
let ff_fc_momentum_y = HerculesImmBox::from(ff_fc_momentum_y.as_slice());
let ff_fc_momentum_z = vec![ff_fc_momentum_z.x, ff_fc_momentum_z.y, ff_fc_momentum_z.z];
let ff_fc_momentum_z = HerculesImmBox::from(ff_fc_momentum_z.as_slice());
let mut runner = runner!(pre_euler);
let variables = variables.to();
HerculesMutBox::from(async_std::task::block_on(async {
runner
.run(
nelr as u64,
iterations as u64,
variables,
areas.to(),
elements_surrounding_elements.to(),
normals.to(),
ff_variable.to(),
ff_fc_density_energy.to(),
ff_fc_momentum_x.to(),
ff_fc_momentum_y.to(),
ff_fc_momentum_z.to(),
)
.await
}))
.as_slice()
.to_vec()
}
fn compare_float(x: f32, y: f32) -> bool {
(x - y).abs() < 1e-5
}
fn compare_floats(xs: &[f32], ys: &[f32]) -> bool {
xs.len() == ys.len() && xs.iter().zip(ys.iter()).all(|(x, y)| compare_float(*x, *y))
}
pub fn cfd_harness(args: CFDInputs) {
let CFDInputs {
data_file,
iterations,
block_size,
pre_euler,
} = args;
assert!(block_size % 16 == 0, "Hercules expects all arrays to be 64-byte aligned, cfd uses structs of arrays that are annoying to deal with if the block_size is not a multiple of 16");
let FarFieldConditions {
ff_variable,
ff_fc_momentum_x,
ff_fc_momentum_y,
ff_fc_momentum_z,
ff_fc_density_energy,
} = set_far_field_conditions();
let GeometryData {
nelr,
areas,
elements_surrounding_elements,
normals,
} = read_domain_geometry(data_file, block_size);
let variables = initialize_variables(nelr, ff_variable.as_slice());
let res_juno = if pre_euler {
run_pre_euler(
nelr,
iterations,
variables.clone(),
areas.as_slice(),
elements_surrounding_elements.as_slice(),
normals.as_slice(),
ff_variable.as_slice(),
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
} else {
run_euler(
nelr,
iterations,
variables.clone(),
areas.as_slice(),
elements_surrounding_elements.as_slice(),
normals.as_slice(),
ff_variable.as_slice(),
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
};
let res_rust = if pre_euler {
rust_cfd::pre_euler(
nelr,
iterations,
variables,
areas.as_slice(),
elements_surrounding_elements.as_slice(),
normals.as_slice(),
ff_variable.as_slice(),
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
} else {
rust_cfd::euler(
nelr,
iterations,
variables,
areas.as_slice(),
elements_surrounding_elements.as_slice(),
normals.as_slice(),
ff_variable.as_slice(),
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
};
if !compare_floats(&res_juno, res_rust.as_slice()) {
assert_eq!(res_juno.len(), res_rust.as_slice().len());
panic!("Mismatch in results");
}
}
#![feature(concat_idents)]
mod rust_cfd;
mod setup;
use clap::Parser; use clap::Parser;
use crate::setup::*; use juno_cfd::{cfd_harness, CFDInputs};
use hercules_rt::{runner, HerculesImmBox, HerculesImmBoxTo, HerculesMutBox, HerculesMutBoxTo};
juno_build::juno!("euler");
juno_build::juno!("pre_euler");
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
struct CFDInputs {
data_file: String,
iterations: usize,
block_size: usize,
#[clap(short = None, long = Some("pre-euler"))]
pre_euler: bool,
}
fn run_euler(
nelr: usize,
iterations: usize,
mut variables: AlignedSlice<f32>,
areas: &[f32],
elements_surrounding_elements: &[i32],
normals: &[f32],
ff_variable: &[f32],
ff_fc_density_energy: &Float3,
ff_fc_momentum_x: &Float3,
ff_fc_momentum_y: &Float3,
ff_fc_momentum_z: &Float3,
) -> Vec<f32> {
let mut variables = HerculesMutBox::from(variables.as_mut_slice());
let areas = HerculesImmBox::from(areas);
let elements_surrounding_elements = HerculesImmBox::from(elements_surrounding_elements);
let normals = HerculesImmBox::from(normals);
let ff_variable = HerculesImmBox::from(ff_variable);
// TODO: Make hercules box handle structs, for now we'll copy into a vec
let ff_fc_density_energy = vec![
ff_fc_density_energy.x,
ff_fc_density_energy.y,
ff_fc_density_energy.z,
];
let ff_fc_density_energy = HerculesImmBox::from(ff_fc_density_energy.as_slice());
let ff_fc_momentum_x = vec![ff_fc_momentum_x.x, ff_fc_momentum_x.y, ff_fc_momentum_x.z];
let ff_fc_momentum_x = HerculesImmBox::from(ff_fc_momentum_x.as_slice());
let ff_fc_momentum_y = vec![ff_fc_momentum_y.x, ff_fc_momentum_y.y, ff_fc_momentum_y.z];
let ff_fc_momentum_y = HerculesImmBox::from(ff_fc_momentum_y.as_slice());
let ff_fc_momentum_z = vec![ff_fc_momentum_z.x, ff_fc_momentum_z.y, ff_fc_momentum_z.z];
let ff_fc_momentum_z = HerculesImmBox::from(ff_fc_momentum_z.as_slice());
let mut runner = runner!(euler);
HerculesMutBox::from(async_std::task::block_on(async {
runner
.run(
nelr as u64,
iterations as u64,
variables.to(),
areas.to(),
elements_surrounding_elements.to(),
normals.to(),
ff_variable.to(),
ff_fc_density_energy.to(),
ff_fc_momentum_x.to(),
ff_fc_momentum_y.to(),
ff_fc_momentum_z.to(),
)
.await
}))
.as_slice()
.to_vec()
}
fn run_pre_euler(
nelr: usize,
iterations: usize,
mut variables: AlignedSlice<f32>,
areas: &[f32],
elements_surrounding_elements: &[i32],
normals: &[f32],
ff_variable: &[f32],
ff_fc_density_energy: &Float3,
ff_fc_momentum_x: &Float3,
ff_fc_momentum_y: &Float3,
ff_fc_momentum_z: &Float3,
) -> Vec<f32> {
let mut variables = HerculesMutBox::from(variables.as_mut_slice());
let areas = HerculesImmBox::from(areas);
let elements_surrounding_elements = HerculesImmBox::from(elements_surrounding_elements);
let normals = HerculesImmBox::from(normals);
let ff_variable = HerculesImmBox::from(ff_variable);
// TODO: Make hercules box handle structs, for now we'll copy into a vec
let ff_fc_density_energy = vec![
ff_fc_density_energy.x,
ff_fc_density_energy.y,
ff_fc_density_energy.z,
];
let ff_fc_density_energy = HerculesImmBox::from(ff_fc_density_energy.as_slice());
let ff_fc_momentum_x = vec![ff_fc_momentum_x.x, ff_fc_momentum_x.y, ff_fc_momentum_x.z];
let ff_fc_momentum_x = HerculesImmBox::from(ff_fc_momentum_x.as_slice());
let ff_fc_momentum_y = vec![ff_fc_momentum_y.x, ff_fc_momentum_y.y, ff_fc_momentum_y.z];
let ff_fc_momentum_y = HerculesImmBox::from(ff_fc_momentum_y.as_slice());
let ff_fc_momentum_z = vec![ff_fc_momentum_z.x, ff_fc_momentum_z.y, ff_fc_momentum_z.z];
let ff_fc_momentum_z = HerculesImmBox::from(ff_fc_momentum_z.as_slice());
let mut runner = runner!(pre_euler);
let variables = variables.to();
HerculesMutBox::from(async_std::task::block_on(async {
runner
.run(
nelr as u64,
iterations as u64,
variables,
areas.to(),
elements_surrounding_elements.to(),
normals.to(),
ff_variable.to(),
ff_fc_density_energy.to(),
ff_fc_momentum_x.to(),
ff_fc_momentum_y.to(),
ff_fc_momentum_z.to(),
)
.await
}))
.as_slice()
.to_vec()
}
fn compare_float(x: f32, y: f32) -> bool {
(x - y).abs() < 1e-5
}
fn compare_floats(xs: &[f32], ys: &[f32]) -> bool {
xs.len() == ys.len() && xs.iter().zip(ys.iter()).all(|(x, y)| compare_float(*x, *y))
}
fn cfd_harness(args: CFDInputs) {
let CFDInputs {
data_file,
iterations,
block_size,
pre_euler,
} = args;
assert!(block_size % 16 == 0, "Hercules expects all arrays to be 64-byte aligned, cfd uses structs of arrays that are annoying to deal with if the block_size is not a multiple of 16");
let FarFieldConditions {
ff_variable,
ff_fc_momentum_x,
ff_fc_momentum_y,
ff_fc_momentum_z,
ff_fc_density_energy,
} = set_far_field_conditions();
let GeometryData {
nelr,
areas,
elements_surrounding_elements,
normals,
} = read_domain_geometry(data_file, block_size);
let variables = initialize_variables(nelr, ff_variable.as_slice());
let res_juno = if pre_euler {
run_pre_euler(
nelr,
iterations,
variables.clone(),
areas.as_slice(),
elements_surrounding_elements.as_slice(),
normals.as_slice(),
ff_variable.as_slice(),
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
} else {
run_euler(
nelr,
iterations,
variables.clone(),
areas.as_slice(),
elements_surrounding_elements.as_slice(),
normals.as_slice(),
ff_variable.as_slice(),
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
};
let res_rust = if pre_euler {
rust_cfd::pre_euler(
nelr,
iterations,
variables,
areas.as_slice(),
elements_surrounding_elements.as_slice(),
normals.as_slice(),
ff_variable.as_slice(),
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
} else {
rust_cfd::euler(
nelr,
iterations,
variables,
areas.as_slice(),
elements_surrounding_elements.as_slice(),
normals.as_slice(),
ff_variable.as_slice(),
&ff_fc_density_energy,
&ff_fc_momentum_x,
&ff_fc_momentum_y,
&ff_fc_momentum_z,
)
};
if !compare_floats(&res_juno, res_rust.as_slice()) {
assert_eq!(res_juno.len(), res_rust.as_slice().len());
panic!("Mismatch in results");
}
}
fn main() { fn main() {
let args = CFDInputs::parse(); let args = CFDInputs::parse();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment