Files
TheRock/rocm-libraries/dnn-providers/hip-kernel-provider/rocke/platform/cpp/helpers/scan.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

218 lines
7.7 KiB
C++

// Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
/*
* helper_rocke.helpers.scan.c -- C99 port of selected symbols from
* rocke/helpers/scan.py.
*
* Ported symbols: lds_zero_i32, block_exclusive_scan_i32.
*
* Each helper reproduces its Python counterpart's rocke_b_* builder-call sequence
* byte-faithfully (same ops, same order, same operands). The host-side control
* structure (the chunk loop, the Hillis-Steele while-loop, the scf_if scoping)
* is reproduced exactly so the emitted op stream is identical to the Python.
*
* scf_if scoping: Python's ``with b.scf_if(cond):`` maps to
* rocke_if_t iff = rocke_b_scf_if(b, cond);
* rocke_b_region_enter(b, iff.then_region);
* ... body ...
* rocke_b_region_leave(b);
*
* Lifetime: every node is arena-owned (rocke_ir_builder_t.arena). Nothing is freed
* individually; the arena bulk-frees the whole graph.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include "rocke/error.hpp"
#include "rocke/helper_rocke.helpers.scan.h"
#include "rocke/ir.h"
/* ----------------------------------------------------------------- helpers */
/* Raise the failure as a ckc::Error (mirroring the Python `raise`); the public
* entry boundary catches it and records status + message on the builder, so the
* C ABI is unchanged. [[noreturn]] keeps the existing `rocke_scan_set_err(...);
* return;` call sites valid -- the trailing return is simply never reached. */
[[noreturn]] static void
rocke_scan_set_err(rocke_ir_builder_t* b, rocke_status_t st, const char* fmt, ...)
{
(void)b;
char msg[ROCKE_ERR_MSG_CAP];
va_list ap;
va_start(ap, fmt);
(void)vsnprintf(msg, sizeof(msg), fmt, ap);
va_end(ap);
msg[sizeof(msg) - 1] = '\0';
ckc::raise_status(st, msg);
}
/* ------------------------------------------------------------- lds_zero_i32 */
void rocke_lds_zero_i32(
rocke_ir_builder_t* b, rocke_value_t* lds_buf, rocke_value_t* tid, int block_size, int length)
{
int chunks;
int c;
rocke_value_t* c_block;
rocke_value_t* c_length;
rocke_value_t* c_zero;
if(b == NULL)
{
return;
}
if(length <= 0)
{
rocke_scan_set_err(b, ROCKE_ERR_VALUE, "length must be > 0 (got %d)", length);
return;
}
chunks = (length + block_size - 1) / block_size;
c_block = rocke_b_const_i32(b, block_size);
c_length = rocke_b_const_i32(b, length);
c_zero = rocke_b_const_i32(b, 0);
for(c = 0; c < chunks; ++c)
{
/* local = b.add(tid, b.mul(b.const_i32(c), c_block)) */
rocke_value_t* local
= rocke_b_add(b, tid, rocke_b_mul(b, rocke_b_const_i32(b, c), c_block));
/* in_bounds = b.cmp_lt(local, c_length) */
rocke_value_t* in_bounds = rocke_b_cmp_lt(b, local, c_length);
/* with b.scf_if(in_bounds): b.smem_store_vN(lds_buf, [local], c_zero, 1) */
rocke_if_t iff = rocke_b_scf_if(b, in_bounds);
rocke_b_region_enter(b, iff.then_region);
{
rocke_value_t* idx[1];
idx[0] = local;
rocke_b_smem_store_vN(b, lds_buf, idx, 1, c_zero, 1);
}
rocke_b_region_leave(b);
}
rocke_b_sync(b);
}
/* ------------------------------------------------- block_exclusive_scan_i32 */
void rocke_block_exclusive_scan_i32(
rocke_ir_builder_t* b, rocke_value_t* lds_buf, rocke_value_t* tid, int block_size, int length)
{
const rocke_type_t* I32;
rocke_value_t* c_length;
rocke_value_t* in_bounds;
int stride;
rocke_value_t* in_range_left;
rocke_value_t* left_idx;
rocke_value_t* left_vec;
rocke_value_t* left_val;
rocke_value_t* shifted;
rocke_if_t iff_final;
if(b == NULL)
{
return;
}
if(length <= 0)
{
rocke_scan_set_err(b, ROCKE_ERR_VALUE, "length must be > 0 (got %d)", length);
return;
}
if(length > block_size)
{
rocke_scan_set_err(b,
ROCKE_ERR_VALUE,
"length %d > block_size %d; multi-pass scans not implemented yet",
length,
block_size);
return;
}
I32 = rocke_i32();
/* c_length = b.const_i32(length); in_bounds = b.cmp_lt(tid, c_length) */
c_length = rocke_b_const_i32(b, length);
in_bounds = rocke_b_cmp_lt(b, tid, c_length);
/* Inclusive Hillis-Steele scan. */
stride = 1;
while(stride < length)
{
/* c_stride = b.const_i32(stride) */
rocke_value_t* c_stride = rocke_b_const_i32(b, stride);
/* do_add = b.land(in_bounds, b.cmp_ge(tid, c_stride)) */
rocke_value_t* do_add = rocke_b_land(b, in_bounds, rocke_b_cmp_ge(b, tid, c_stride));
/* self_idx = b.select(in_bounds, tid, b.const_i32(0)) */
rocke_value_t* self_idx = rocke_b_select(b, in_bounds, tid, rocke_b_const_i32(b, 0));
/* left_idx = b.select(do_add, b.sub(tid, c_stride), b.const_i32(0)) */
rocke_value_t* l_idx
= rocke_b_select(b, do_add, rocke_b_sub(b, tid, c_stride), rocke_b_const_i32(b, 0));
/* self_vec = b.smem_load_vN(lds_buf, self_idx, dtype=I32, n=1) */
rocke_value_t* self_vec;
rocke_value_t* l_vec;
rocke_value_t* self_val;
rocke_value_t* l_val;
rocke_value_t* new_val;
rocke_if_t iff;
rocke_value_t* sidx[1];
rocke_value_t* lidx[1];
rocke_value_t* widx[1];
sidx[0] = self_idx;
self_vec = rocke_b_smem_load_vN(b, lds_buf, sidx, 1, I32, 1);
/* left_vec = b.smem_load_vN(lds_buf, left_idx, dtype=I32, n=1) */
lidx[0] = l_idx;
l_vec = rocke_b_smem_load_vN(b, lds_buf, lidx, 1, I32, 1);
/* self_val = b.vec_extract(self_vec, 0); left_val = b.vec_extract(left_vec, 0) */
self_val = rocke_b_vec_extract(b, self_vec, 0);
l_val = rocke_b_vec_extract(b, l_vec, 0);
/* new_val = b.add(self_val, left_val) */
new_val = rocke_b_add(b, self_val, l_val);
/* b.sync() */
rocke_b_sync(b);
/* with b.scf_if(do_add): b.smem_store_vN(lds_buf, [tid], new_val, 1) */
iff = rocke_b_scf_if(b, do_add);
rocke_b_region_enter(b, iff.then_region);
{
widx[0] = tid;
rocke_b_smem_store_vN(b, lds_buf, widx, 1, new_val, 1);
}
rocke_b_region_leave(b);
/* b.sync() */
rocke_b_sync(b);
stride *= 2;
}
/* Convert inclusive -> exclusive via a one-position right-shift. */
/* in_range_left = b.land(in_bounds, b.cmp_gt(tid, b.const_i32(0))) */
in_range_left = rocke_b_land(b, in_bounds, rocke_b_cmp_gt(b, tid, rocke_b_const_i32(b, 0)));
/* left_idx = b.select(in_range_left, b.sub(tid, b.const_i32(1)), b.const_i32(0)) */
left_idx = rocke_b_select(
b, in_range_left, rocke_b_sub(b, tid, rocke_b_const_i32(b, 1)), rocke_b_const_i32(b, 0));
/* left_vec = b.smem_load_vN(lds_buf, left_idx, dtype=I32, n=1) */
{
rocke_value_t* lidx2[1];
lidx2[0] = left_idx;
left_vec = rocke_b_smem_load_vN(b, lds_buf, lidx2, 1, I32, 1);
}
/* left_val = b.vec_extract(left_vec, 0) */
left_val = rocke_b_vec_extract(b, left_vec, 0);
/* shifted = b.select(in_range_left, left_val, b.const_i32(0)) */
shifted = rocke_b_select(b, in_range_left, left_val, rocke_b_const_i32(b, 0));
/* b.sync() */
rocke_b_sync(b);
/* with b.scf_if(in_bounds): b.smem_store_vN(lds_buf, [tid], shifted, 1) */
iff_final = rocke_b_scf_if(b, in_bounds);
rocke_b_region_enter(b, iff_final.then_region);
{
rocke_value_t* widx2[1];
widx2[0] = tid;
rocke_b_smem_store_vN(b, lds_buf, widx2, 1, shifted, 1);
}
rocke_b_region_leave(b);
/* b.sync() */
rocke_b_sync(b);
}