Skip to content

Commit ac329f1

Browse files
committed
bench: add debug_grid and residual_like probes for residual 2D census
1 parent 4a504b8 commit ac329f1

5 files changed

Lines changed: 166 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
#include <hip/hip_runtime.h>
3+
extern "C" __global__ void debug_grid(int* out, int* hits, int* counter, int gx) {
4+
if (threadIdx.x != 0 || threadIdx.y != 0 || threadIdx.z != 0) return;
5+
int x = blockIdx.x;
6+
int y = blockIdx.y;
7+
int idx = atomicAdd(counter, 1);
8+
if (idx < 4096) out[idx] = (y << 16) | x;
9+
atomicAdd(&hits[y * gx + x], 1);
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
#include <hip/hip_runtime.h>
3+
extern "C" __global__ void residual_atomic(float* y, int n, int m, int gx) {
4+
int idx = (blockIdx.y * gx + blockIdx.x);
5+
if (idx >= n * gx) return;
6+
atomicAdd(&y[idx], 1.0f);
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
#include <hip/hip_runtime.h>
3+
extern "C" __global__ void residual_like(float* y, int n, int m, int gx) {
4+
int x = blockIdx.x;
5+
int y0 = blockIdx.y;
6+
// Token = y * 64 + x? Not exact; just increment one element per workgroup in a pattern.
7+
int idx = (y0 * gx + x);
8+
y[idx] += 1.0f;
9+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
use hip_bridge::HipRuntime;
3+
use redline_dispatch::aql::{Gfx10Pm4CommandBuffer, Gfx12Pm4CommandBuffer, GpuSelector, KernargPool, LaunchGeometry, Runtime, SingleQueuePm4Ib, load_symbols};
4+
use std::sync::Arc;
5+
fn run_hip(gx: u32, gy: u32, hsaco: &[u8]) -> anyhow::Result<(Vec<(u32,u32)>, Vec<u32>)> {
6+
let hip = HipRuntime::load()?; hip.set_device(0)?;
7+
let module = hip.module_load_data(hsaco)?; let func = hip.module_get_function(&module, "debug_grid")?;
8+
let total_wg = (gx * gy) as usize;
9+
let out = hip.malloc(total_wg * 4)?; let hits = hip.malloc((gx*gy) as usize *4)?; let counter = hip.malloc(4)?;
10+
hip.memset(&out, 0, out.size())?; hip.memset(&hits, 0, hits.size())?; hip.memset(&counter, 0, counter.size())?; hip.device_synchronize()?;
11+
let mut kernarg = vec![0u8; 32];
12+
let out_ptr = out.as_ptr() as u64; let hits_ptr = hits.as_ptr() as u64; let counter_ptr = counter.as_ptr() as u64;
13+
kernarg[0..8].copy_from_slice(&out_ptr.to_ne_bytes()); kernarg[8..16].copy_from_slice(&hits_ptr.to_ne_bytes()); kernarg[16..24].copy_from_slice(&counter_ptr.to_ne_bytes()); kernarg[24..28].copy_from_slice(&(gx as i32).to_ne_bytes());
14+
let stream = hip.stream_create()?;
15+
unsafe { hip.launch_kernel_blob(&func, [gx, gy, 1], [32,1,1], 0, Some(&stream), &mut kernarg)?; }
16+
hip.stream_synchronize(&stream)?;
17+
let mut out_bytes = vec![0u8; total_wg*4]; let mut hits_bytes = vec![0u8; (gx*gy) as usize*4]; let mut counter_bytes = vec![0u8; 4];
18+
hip.memcpy_dtoh(&mut out_bytes, &out)?; hip.memcpy_dtoh(&mut hits_bytes, &hits)?; hip.memcpy_dtoh(&mut counter_bytes, &counter)?;
19+
let counter_val = u32::from_ne_bytes(counter_bytes[0..4].try_into().unwrap());
20+
let mut out_pairs = Vec::new(); for i in 0..counter_val as usize { let v = u32::from_ne_bytes(out_bytes[i*4..i*4+4].try_into().unwrap()); out_pairs.push((v & 0xFFFF, v >> 16)); }
21+
let mut hits_vals = Vec::new(); for i in 0..(gx*gy) as usize { hits_vals.push(u32::from_ne_bytes(hits_bytes[i*4..i*4+4].try_into().unwrap())); }
22+
Ok((out_pairs, hits_vals))
23+
}
24+
fn run_redline(gx: u32, gy: u32, hsaco: &[u8]) -> anyhow::Result<(Vec<(u32,u32)>, Vec<u32>)> {
25+
let runtime = Runtime::initialize(load_symbols()?)?;
26+
let ordinal = std::env::var("HIP_VISIBLE_DEVICES").or_else(|_| std::env::var("ROCR_VISIBLE_DEVICES")).ok().and_then(|v| v.split(',').next().and_then(|s| s.trim().parse::<usize>().ok())).unwrap_or(0);
27+
let device = runtime.select_gpu(GpuSelector::Ordinal(ordinal)).or_else(|_| runtime.select_gpu(GpuSelector::Ordinal(0)))?;
28+
let exec = redline_dispatch::aql::Executable::load(&device, Arc::<[u8]>::from(hsaco))?;
29+
let kernel = exec.kernel("debug_grid.kd")?;
30+
let pool = KernargPool::discover(&device)?;
31+
let hip = HipRuntime::load()?; hip.set_device(0)?;
32+
let total_wg = (gx * gy) as usize;
33+
let out = hip.malloc(total_wg * 4)?; let hits = hip.malloc((gx*gy) as usize *4)?; let counter = hip.malloc(4)?;
34+
hip.memset(&out, 0, out.size())?; hip.memset(&hits, 0, hits.size())?; hip.memset(&counter, 0, counter.size())?; hip.device_synchronize()?;
35+
let mut karg = pool.allocate_for(kernel.metadata())?;
36+
let bytes = karg.as_mut_bytes(); bytes.fill(0);
37+
let out_ptr = out.as_ptr() as u64; let hits_ptr = hits.as_ptr() as u64; let counter_ptr = counter.as_ptr() as u64;
38+
bytes[0..8].copy_from_slice(&out_ptr.to_ne_bytes()); bytes[8..16].copy_from_slice(&hits_ptr.to_ne_bytes()); bytes[16..24].copy_from_slice(&counter_ptr.to_ne_bytes()); bytes[24..28].copy_from_slice(&(gx as i32).to_ne_bytes());
39+
let geometry = LaunchGeometry::from_workgroups([gx, gy, 1], [32,1,1])?;
40+
let is_gfx12 = device.name().contains("gfx12");
41+
let (mut ib, mut ownership) = if is_gfx12 {
42+
let mut cmds = Gfx12Pm4CommandBuffer::new_stateful(); cmds.dispatch(&kernel, geometry, 0, karg.address())?;
43+
let mut oc = Gfx12Pm4CommandBuffer::new(); oc.acquire_system_gfx12();
44+
(SingleQueuePm4Ib::create(&device, &pool, &cmds)?, SingleQueuePm4Ib::create(&device, &pool, &oc)?)
45+
} else {
46+
let mut cmds = Gfx10Pm4CommandBuffer::new_stateful(); cmds.dispatch(&kernel, geometry, 0, karg.address())?;
47+
let mut oc = Gfx10Pm4CommandBuffer::new(); oc.acquire_system();
48+
let ib = if device.name().contains("gfx11") { SingleQueuePm4Ib::create_gfx11(&device, &pool, &cmds)? } else { SingleQueuePm4Ib::create_gfx10(&device, &pool, &cmds)? };
49+
let ownership = if device.name().contains("gfx11") { SingleQueuePm4Ib::create_gfx11(&device, &pool, &oc)? } else { SingleQueuePm4Ib::create_gfx10(&device, &pool, &oc)? };
50+
(ib, ownership)
51+
};
52+
let _keep = karg;
53+
unsafe { ownership.replay_and_wait()?; } unsafe { ib.replay_and_wait()?; }
54+
let mut out_bytes = vec![0u8; total_wg*4]; let mut hits_bytes = vec![0u8; (gx*gy) as usize*4]; let mut counter_bytes = vec![0u8; 4];
55+
hip.memcpy_dtoh(&mut out_bytes, &out)?; hip.memcpy_dtoh(&mut hits_bytes, &hits)?; hip.memcpy_dtoh(&mut counter_bytes, &counter)?;
56+
let counter_val = u32::from_ne_bytes(counter_bytes[0..4].try_into().unwrap());
57+
let mut out_pairs = Vec::new(); for i in 0..counter_val as usize { let v = u32::from_ne_bytes(out_bytes[i*4..i*4+4].try_into().unwrap()); out_pairs.push((v & 0xFFFF, v >> 16)); }
58+
let mut hits_vals = Vec::new(); for i in 0..(gx*gy) as usize { hits_vals.push(u32::from_ne_bytes(hits_bytes[i*4..i*4+4].try_into().unwrap())); }
59+
Ok((out_pairs, hits_vals))
60+
}
61+
fn main() -> anyhow::Result<()> {
62+
let args: Vec<String> = std::env::args().collect();
63+
let mut gx = 128; let mut gy = 2; let mut arch = "gfx1151".to_string();
64+
for i in 0..args.len() { if args[i]=="--gx" { gx=args[i+1].parse()?; } if args[i]=="--gy" { gy=args[i+1].parse()?; } if args[i]=="--arch" { arch=args[i+1].clone(); } }
65+
let hsaco_path = match arch.as_str() { "gfx1151" => "/tmp/debug_grid_gfx1151.hsaco", "gfx1201" => "/tmp/debug_grid_gfx1201.hsaco", "gfx1100" => "/tmp/debug_grid_gfx1151.hsaco", _ => "/tmp/debug_grid.hsaco", };
66+
let hsaco = std::fs::read(hsaco_path)?;
67+
println!("=== HIP gx={} gy={} arch={} ===", gx, gy, arch);
68+
match run_hip(gx, gy, &hsaco) { Ok((pairs, hits)) => { println!("HIP total {}", pairs.len()); let mut counts = std::collections::BTreeMap::new(); for (x,y) in &pairs { *counts.entry((*x,*y)).or_insert(0) +=1; } println!("HIP unique {}", counts.len()); for ((x,y),c) in &counts { println!(" ({},{}) x{}", x,y,c); } println!("HIP hits {:?}", hits); if counts.values().all(|&c| c==1) { println!("HIP: all once"); } }, Err(e) => println!("HIP failed: {:#}", e), }
69+
println!("=== Redline gx={} gy={} arch={} ===", gx, gy, arch);
70+
match run_redline(gx, gy, &hsaco) { Ok((pairs, hits)) => { println!("Redline total {}", pairs.len()); let mut counts = std::collections::BTreeMap::new(); for (x,y) in &pairs { *counts.entry((*x,*y)).or_insert(0) +=1; } println!("Redline unique {}", counts.len()); for ((x,y),c) in &counts { println!(" ({},{}) x{}", x,y,c); } println!("Redline hits {:?}", hits); if counts.values().all(|&c| c==1) { println!("Redline: all once"); } for y in 0..gy { for x in 0..gx { if hits[(y*gx+x) as usize]!=1 { println!("Redline missing at ({},{}) hits {}", x,y, hits[(y*gx+x) as usize]); } } } }, Err(e) => println!("Redline failed: {:#}", e), }
71+
Ok(())
72+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
use hip_bridge::HipRuntime;
3+
use redline_dispatch::aql::{Gfx10Pm4CommandBuffer, Gfx12Pm4CommandBuffer, GpuSelector, KernargPool, LaunchGeometry, Runtime, SingleQueuePm4Ib, load_symbols};
4+
use std::sync::Arc;
5+
fn run_hip(gx: u32, gy: u32, n: u32, m: u32, iterations: usize, hsaco: &[u8]) -> anyhow::Result<Vec<f32>> {
6+
let hip = HipRuntime::load()?; hip.set_device(0)?;
7+
let module = hip.module_load_data(hsaco)?; let func = hip.module_get_function(&module, "residual_like")?;
8+
let total = (gx*gy) as usize;
9+
let y = hip.malloc(total*4)?;
10+
hip.memset(&y, 0, y.size())?; hip.device_synchronize()?;
11+
let mut kernarg = vec![0u8; 24];
12+
let y_ptr = y.as_ptr() as u64;
13+
kernarg[0..8].copy_from_slice(&y_ptr.to_ne_bytes()); kernarg[8..12].copy_from_slice(&(n as i32).to_ne_bytes()); kernarg[12..16].copy_from_slice(&(m as i32).to_ne_bytes()); kernarg[16..20].copy_from_slice(&(gx as i32).to_ne_bytes());
14+
let stream = hip.stream_create()?;
15+
for _ in 0..iterations { unsafe { hip.launch_kernel_blob(&func, [gx, gy, 1], [32,1,1], 0, Some(&stream), &mut kernarg)?; } }
16+
hip.stream_synchronize(&stream)?;
17+
let mut bytes = vec![0u8; total*4]; hip.memcpy_dtoh(&mut bytes, &y)?;
18+
let vals: Vec<f32> = bytes.chunks_exact(4).map(|c| f32::from_ne_bytes(c.try_into().unwrap())).collect();
19+
Ok(vals)
20+
}
21+
fn run_redline(gx: u32, gy: u32, n: u32, m: u32, iterations: usize, hsaco: &[u8], add_dep: bool) -> anyhow::Result<Vec<f32>> {
22+
let runtime = Runtime::initialize(load_symbols()?)?;
23+
let ordinal = std::env::var("HIP_VISIBLE_DEVICES").or_else(|_| std::env::var("ROCR_VISIBLE_DEVICES")).ok().and_then(|v| v.split(',').next().and_then(|s| s.trim().parse::<usize>().ok())).unwrap_or(0);
24+
let device = runtime.select_gpu(GpuSelector::Ordinal(ordinal)).or_else(|_| runtime.select_gpu(GpuSelector::Ordinal(0)))?;
25+
let exec = redline_dispatch::aql::Executable::load(&device, Arc::<[u8]>::from(hsaco))?;
26+
let kernel = exec.kernel("residual_like.kd")?;
27+
let pool = KernargPool::discover(&device)?;
28+
let hip = HipRuntime::load()?; hip.set_device(0)?;
29+
let total = (gx*gy) as usize;
30+
let y = hip.malloc(total*4)?;
31+
hip.memset(&y, 0, y.size())?; hip.device_synchronize()?;
32+
let mut karg = pool.allocate_for(kernel.metadata())?;
33+
let bytes = karg.as_mut_bytes(); bytes.fill(0);
34+
let y_ptr = y.as_ptr() as u64;
35+
bytes[0..8].copy_from_slice(&y_ptr.to_ne_bytes()); bytes[8..12].copy_from_slice(&(n as i32).to_ne_bytes()); bytes[12..16].copy_from_slice(&(m as i32).to_ne_bytes()); bytes[16..20].copy_from_slice(&(gx as i32).to_ne_bytes());
36+
let geometry = LaunchGeometry::from_workgroups([gx, gy, 1], [32,1,1])?;
37+
let is_gfx12 = device.name().contains("gfx12");
38+
let (mut ib, mut ownership) = if is_gfx12 {
39+
let mut cmds = Gfx12Pm4CommandBuffer::new_stateful();
40+
for i in 0..iterations { cmds.dispatch(&kernel, geometry, 0, karg.address())?; if add_dep && i + 1 < iterations { cmds.dependency_rmw_same_agent_gfx12(); } }
41+
let mut oc = Gfx12Pm4CommandBuffer::new(); oc.acquire_system_gfx12();
42+
(SingleQueuePm4Ib::create(&device, &pool, &cmds)?, SingleQueuePm4Ib::create(&device, &pool, &oc)?)
43+
} else {
44+
let mut cmds = Gfx10Pm4CommandBuffer::new_stateful();
45+
for i in 0..iterations { cmds.dispatch(&kernel, geometry, 0, karg.address())?; if add_dep && i + 1 < iterations { cmds.dependency_rmw_same_agent(); } }
46+
let mut oc = Gfx10Pm4CommandBuffer::new(); oc.acquire_system();
47+
let ib = if device.name().contains("gfx11") { SingleQueuePm4Ib::create_gfx11(&device, &pool, &cmds)? } else { SingleQueuePm4Ib::create_gfx10(&device, &pool, &cmds)? };
48+
let ownership = if device.name().contains("gfx11") { SingleQueuePm4Ib::create_gfx11(&device, &pool, &oc)? } else { SingleQueuePm4Ib::create_gfx10(&device, &pool, &oc)? };
49+
(ib, ownership)
50+
};
51+
let _keep = karg;
52+
unsafe { ownership.replay_and_wait()?; } unsafe { ib.replay_and_wait()?; }
53+
let mut bytes = vec![0u8; total*4]; hip.memcpy_dtoh(&mut bytes, &y)?;
54+
let vals: Vec<f32> = bytes.chunks_exact(4).map(|c| f32::from_ne_bytes(c.try_into().unwrap())).collect();
55+
Ok(vals)
56+
}
57+
fn main() -> anyhow::Result<()> {
58+
let args: Vec<String> = std::env::args().collect();
59+
let mut gx = 128; let mut gy = 2; let mut n = 128; let mut m = 2048; let mut iterations = 4; let mut arch = "gfx1151".to_string(); let mut dep = false;
60+
for i in 0..args.len() { match args[i].as_str() { "--gx"=>{gx=args[i+1].parse()?;} "--gy"=>{gy=args[i+1].parse()?;} "--n"=>{n=args[i+1].parse()?;} "--m"=>{m=args[i+1].parse()?;} "--iterations"=>{iterations=args[i+1].parse()?;} "--arch"=>{arch=args[i+1].clone();} "--dep"=>{dep=true;} _=>{} } }
61+
let hsaco_path = match arch.as_str() { "gfx1151" => "/tmp/residual_like_gfx1151.hsaco", "gfx1201" => "/tmp/residual_like_gfx1201.hsaco", _ => "/tmp/residual_like_gfx1151.hsaco", };
62+
let hsaco = std::fs::read(hsaco_path)?;
63+
println!("=== HIP gx={} gy={} n={} m={} iters={} arch={} ===", gx, gy, n, m, iterations, arch);
64+
match run_hip(gx, gy, n, m, iterations, &hsaco) { Ok(vals) => { println!("HIP vals (first 10): {:?}", &vals[..vals.len().min(10)]); let all1 = vals.iter().all(|&v| (v - iterations as f32).abs() < 1e-5); println!("HIP all == {}: {}", iterations, all1); } Err(e) => println!("HIP failed: {:#}", e), }
65+
println!("=== Redline gx={} gy={} n={} m={} iters={} arch={} dep={} ===", gx, gy, n, m, iterations, arch, dep);
66+
match run_redline(gx, gy, n, m, iterations, &hsaco, dep) { Ok(vals) => { println!("Redline vals (first 10): {:?}", &vals[..vals.len().min(10)]); let all1 = vals.iter().all(|&v| (v - iterations as f32).abs() < 1e-5); println!("Redline all == {}: {}", iterations, all1); let mut bad=0; for (i,&v) in vals.iter().enumerate() { if (v - iterations as f32).abs() > 1e-5 { println!("Redline elem {} val {}", i, v); bad+=1; if bad>20 {break;} } } } Err(e) => println!("Redline failed: {:#}", e), }
67+
Ok(())
68+
}

0 commit comments

Comments
 (0)