mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[rs] Merge #809
809: Add overflow detection to hello-compute r=kvark a=danwilhelm Description The `hello-compute` example sometimes gives incorrect results if an intermediate Collatz value overflows. Proposed Solution We can detect overflows before they occur, since the `3n+1` step is the only possible overflow. (WGSL only supports u32.) Example `cargo run --example hello-compute 77031 837799 8400511 63728127` > Incorrect Current Output: `[350, 524, 312, 346]` > Correct Output: `[350, 524, 685, 949]` > Proposed Solution: `[350, 524, OVERFLOW, OVERFLOW]` Notes - The `hello-compute` example appears to be [borrowed from naga](https://github.com/gfx-rs/naga/blob/master/tests/in/collatz.wgsl), so this would cause the implementations to differ. - Hexadecimal literals are not yet implemented in naga for WGSL shaders, so the shader literals are not as pretty as they could be. - Revised terminology `times` -> `steps` to be consistent with [Wikipedia](https://en.wikipedia.org/wiki/Collatz_conjecture). Co-authored-by: Dan Wilhelm <dan@danwilhelm.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
use std::{borrow::Cow, convert::TryInto, str::FromStr};
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
// Indicates a u32 overflow in an intermediate Collatz value
|
||||
const OVERFLOW: u32 = 0xffffffff;
|
||||
|
||||
async fn run() {
|
||||
let numbers = if std::env::args().len() <= 1 {
|
||||
let default = vec![1, 2, 3, 4];
|
||||
@@ -13,10 +16,19 @@ async fn run() {
|
||||
.collect()
|
||||
};
|
||||
|
||||
let times = execute_gpu(numbers).await;
|
||||
println!("Times: {:?}", times);
|
||||
let steps = execute_gpu(numbers).await;
|
||||
|
||||
let disp_steps: Vec<String> = steps
|
||||
.iter()
|
||||
.map(|&n| match n {
|
||||
OVERFLOW => "OVERFLOW".to_string(),
|
||||
_ => n.to_string(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
println!("Steps: [{}]", disp_steps.join(", "));
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
log::info!("Times: {:?}", times);
|
||||
log::info!("Steps: [{}]", disp_steps.join(", "));
|
||||
}
|
||||
|
||||
async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
|
||||
@@ -194,6 +206,15 @@ mod tests {
|
||||
pollster::block_on(assert_execute_gpu(input, vec![5, 15, 6, 19]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compute_overflow() {
|
||||
let input = vec![77031, 837799, 8400511, 63728127];
|
||||
pollster::block_on(assert_execute_gpu(
|
||||
input,
|
||||
vec![350, 524, OVERFLOW, OVERFLOW],
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multithreaded_compute() {
|
||||
use std::{sync::mpsc, thread, time::Duration};
|
||||
|
||||
@@ -23,6 +23,11 @@ fn collatz_iterations(n_base: u32) -> u32{
|
||||
n = n / 2u;
|
||||
}
|
||||
else {
|
||||
// Overflow? (i.e. 3*n + 1 > 0xffffffffu?)
|
||||
if (n >= 1431655765u) { // 0x55555555u
|
||||
return 4294967295u; // 0xffffffffu
|
||||
}
|
||||
|
||||
n = 3u * n + 1u;
|
||||
}
|
||||
i = i + 1u;
|
||||
|
||||
Reference in New Issue
Block a user