Uploaded sanitized BC250/ROCm Repository.
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Minimal HIP diagnostic — step-by-step GPU compute validation
|
||||
* Tests each operation individually with timeout awareness
|
||||
*
|
||||
* Compile: hipcc --offload-arch=gfx1010 -o hip_minimal_test hip_minimal_test.cpp
|
||||
* Run: HSA_OVERRIDE_GFX_VERSION=10.1.0 ./hip_minimal_test
|
||||
*/
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#define HIP_CHECK(call) do { \
|
||||
hipError_t err = call; \
|
||||
if (err != hipSuccess) { \
|
||||
fprintf(stderr, "HIP ERROR [%d]: %s at %s:%d\n", \
|
||||
(int)err, hipGetErrorString(err), __FILE__, __LINE__); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
__global__ void simpleKernel(int* out) {
|
||||
out[threadIdx.x] = threadIdx.x * 2;
|
||||
}
|
||||
|
||||
int main() {
|
||||
setbuf(stdout, NULL); // Force unbuffered output
|
||||
setbuf(stderr, NULL);
|
||||
|
||||
printf("STEP 0: HIP init\n");
|
||||
int count;
|
||||
HIP_CHECK(hipGetDeviceCount(&count));
|
||||
printf(" Devices: %d\n", count);
|
||||
|
||||
hipDeviceProp_t p;
|
||||
HIP_CHECK(hipGetDeviceProperties(&p, 0));
|
||||
printf(" Device: %s, CU=%d, Mem=%zuMB, isIntegrated=%d\n",
|
||||
p.name, p.multiProcessorCount, p.totalGlobalMem/(1024*1024), p.integrated);
|
||||
|
||||
printf("STEP 1: hipMalloc (small: 256 bytes)\n");
|
||||
int *d_buf = nullptr;
|
||||
HIP_CHECK(hipMalloc(&d_buf, 256));
|
||||
printf(" OK: d_buf=%p\n", (void*)d_buf);
|
||||
|
||||
printf("STEP 2: hipMemset\n");
|
||||
HIP_CHECK(hipMemset(d_buf, 0, 256));
|
||||
printf(" OK\n");
|
||||
|
||||
printf("STEP 3: hipMemcpy H2D (64 ints)\n");
|
||||
int h_buf[64];
|
||||
for (int i = 0; i < 64; i++) h_buf[i] = i + 100;
|
||||
HIP_CHECK(hipMemcpy(d_buf, h_buf, 256, hipMemcpyHostToDevice));
|
||||
printf(" OK\n");
|
||||
|
||||
printf("STEP 4: Launch kernel (1 block, 32 threads)\n");
|
||||
simpleKernel<<<1, 32>>>(d_buf);
|
||||
HIP_CHECK(hipGetLastError());
|
||||
printf(" Launched\n");
|
||||
|
||||
printf("STEP 5: hipDeviceSynchronize\n");
|
||||
HIP_CHECK(hipDeviceSynchronize());
|
||||
printf(" OK\n");
|
||||
|
||||
printf("STEP 6: hipMemcpy D2H\n");
|
||||
int h_out[64];
|
||||
memset(h_out, 0, 256);
|
||||
HIP_CHECK(hipMemcpy(h_out, d_buf, 128, hipMemcpyDeviceToHost));
|
||||
printf(" OK\n");
|
||||
|
||||
printf("STEP 7: Verify results\n");
|
||||
int pass = 1;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (h_out[i] != i * 2) {
|
||||
printf(" FAIL: h_out[%d]=%d expected %d\n", i, h_out[i], i*2);
|
||||
pass = 0;
|
||||
}
|
||||
}
|
||||
if (pass) printf(" ALL 32 VALUES CORRECT\n");
|
||||
|
||||
HIP_CHECK(hipFree(d_buf));
|
||||
printf("\nRESULT: %s\n", pass ? "PASS — ROCm HIP COMPUTE WORKS" : "FAIL");
|
||||
return pass ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* HIP Minimal Probe — Safe diagnostic for AMD BC-250
|
||||
* Step-by-step: each step prints BEFORE attempting, so we know where it hangs/crashes
|
||||
*
|
||||
* Compile: hipcc --offload-arch=gfx1010 -o hip_probe hip_probe.cpp
|
||||
* Run: HSA_OVERRIDE_GFX_VERSION=10.1.0 ./hip_probe
|
||||
*/
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstdio>
|
||||
#include <unistd.h> // _exit() — bypasses C++ destructors
|
||||
|
||||
int main() {
|
||||
printf("PROBE: Starting HIP minimal probe...\n");
|
||||
fflush(stdout);
|
||||
|
||||
// Step 1: hipGetDeviceCount
|
||||
printf("PROBE [1/6]: hipGetDeviceCount... ");
|
||||
fflush(stdout);
|
||||
int count = 0;
|
||||
hipError_t err = hipGetDeviceCount(&count);
|
||||
if (err != hipSuccess) {
|
||||
printf("FAILED: %s\n", hipGetErrorString(err));
|
||||
return 1;
|
||||
}
|
||||
printf("OK (%d devices)\n", count);
|
||||
fflush(stdout);
|
||||
|
||||
if (count == 0) {
|
||||
printf("PROBE: No devices. Exiting.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Step 2: hipGetDeviceProperties
|
||||
printf("PROBE [2/6]: hipGetDeviceProperties... ");
|
||||
fflush(stdout);
|
||||
hipDeviceProp_t props;
|
||||
err = hipGetDeviceProperties(&props, 0);
|
||||
if (err != hipSuccess) {
|
||||
printf("FAILED: %s\n", hipGetErrorString(err));
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
printf(" Name: %s\n", props.name);
|
||||
printf(" GCN Arch: %s\n", props.gcnArchName);
|
||||
printf(" CUs: %d\n", props.multiProcessorCount);
|
||||
printf(" Total Mem: %zu MB\n", props.totalGlobalMem / (1024*1024));
|
||||
printf(" Managed Memory: %s\n", props.managedMemory ? "YES" : "NO");
|
||||
printf(" Concurrent Managed: %s\n", props.concurrentManagedAccess ? "YES" : "NO");
|
||||
printf(" Integrated (APU): %s\n", props.integrated ? "YES" : "NO");
|
||||
printf(" pageableMemoryAccess: %s\n", props.pageableMemoryAccess ? "YES" : "NO");
|
||||
fflush(stdout);
|
||||
|
||||
// Step 3: hipSetDevice
|
||||
printf("PROBE [3/6]: hipSetDevice(0)... ");
|
||||
fflush(stdout);
|
||||
err = hipSetDevice(0);
|
||||
if (err != hipSuccess) {
|
||||
printf("FAILED: %s\n", hipGetErrorString(err));
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
fflush(stdout);
|
||||
|
||||
// Step 4: Try hipHostMalloc (pinned host memory — safest for APU)
|
||||
printf("PROBE [4/6]: hipHostMalloc (64 KB, coherent)... ");
|
||||
fflush(stdout);
|
||||
float* hostPtr = nullptr;
|
||||
err = hipHostMalloc(&hostPtr, 64 * 1024, hipHostMallocCoherent);
|
||||
if (err != hipSuccess) {
|
||||
printf("FAILED: %s\n", hipGetErrorString(err));
|
||||
printf(" Trying hipHostMallocDefault...\n");
|
||||
err = hipHostMalloc(&hostPtr, 64 * 1024, hipHostMallocDefault);
|
||||
if (err != hipSuccess) {
|
||||
printf(" Also FAILED: %s\n", hipGetErrorString(err));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
printf("OK (ptr=%p)\n", (void*)hostPtr);
|
||||
fflush(stdout);
|
||||
|
||||
// Step 5: Try hipMallocManaged (unified memory)
|
||||
printf("PROBE [5/6]: hipMallocManaged (64 KB)... ");
|
||||
fflush(stdout);
|
||||
float* managedPtr = nullptr;
|
||||
err = hipMallocManaged(&managedPtr, 64 * 1024);
|
||||
if (err != hipSuccess) {
|
||||
printf("FAILED: %s (this may be expected without XNACK)\n", hipGetErrorString(err));
|
||||
fflush(stdout);
|
||||
} else {
|
||||
printf("OK (ptr=%p)\n", (void*)managedPtr);
|
||||
fflush(stdout);
|
||||
// Write test
|
||||
managedPtr[0] = 42.0f;
|
||||
printf(" Write test: managedPtr[0] = %f\n", managedPtr[0]);
|
||||
fflush(stdout);
|
||||
hipFree(managedPtr);
|
||||
}
|
||||
|
||||
// Step 6: Free host memory — do NOT call hipDeviceReset()!
|
||||
// hipDeviceReset() causes KIQ fence timeout -> system hang on BC-250
|
||||
printf("PROBE [6/6]: Cleanup (no device reset)... ");
|
||||
fflush(stdout);
|
||||
hipHostFree(hostPtr);
|
||||
// hipDeviceReset() intentionally omitted — crashes BC-250
|
||||
printf("OK\n");
|
||||
fflush(stdout);
|
||||
|
||||
printf("\nPROBE: ALL STEPS COMPLETED SUCCESSFULLY\n");
|
||||
fflush(stdout);
|
||||
_exit(0); // HARD EXIT — bypasses HIP runtime destructors that crash BC-250
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* HIP Vector Addition Test — AMD BC-250 ROCm Validation
|
||||
*
|
||||
* Uses hipMallocManaged (unified memory) — REQUIRED for BC-250 which is an
|
||||
* APU-like device with shared system memory (no dedicated VRAM).
|
||||
* Standard hipMalloc + hipMemcpy will crash the system!
|
||||
*
|
||||
* Verifies GPU compute works end-to-end:
|
||||
* 1. HIP runtime initializes & device query
|
||||
* 2. Managed memory allocation (unified address space)
|
||||
* 3. GPU kernel execution
|
||||
* 4. Results are numerically correct
|
||||
*
|
||||
* Compile: hipcc --offload-arch=gfx1010 -o hip_vector_add hip_vector_add.cpp
|
||||
* Run: HSA_OVERRIDE_GFX_VERSION=10.1.0 ./hip_vector_add
|
||||
*/
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <unistd.h> // _exit() — bypasses C++ destructors
|
||||
|
||||
#define HIP_CHECK(call) do { \
|
||||
hipError_t err = call; \
|
||||
if (err != hipSuccess) { \
|
||||
fprintf(stderr, "HIP Error: %s at %s:%d\n", \
|
||||
hipGetErrorString(err), __FILE__, __LINE__); \
|
||||
fflush(stderr); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
__global__ void vectorAdd(const float* A, const float* B, float* C, int N) {
|
||||
int i = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
if (i < N) {
|
||||
C[i] = A[i] + B[i];
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("=== HIP Vector Addition Test (Managed Memory) ===\n");
|
||||
printf(" Target: AMD BC-250 (gfx1013, APU shared memory)\n\n");
|
||||
fflush(stdout);
|
||||
|
||||
// Step 1: Query device
|
||||
printf("[1/4] Querying HIP device... ");
|
||||
fflush(stdout);
|
||||
int deviceCount = 0;
|
||||
HIP_CHECK(hipGetDeviceCount(&deviceCount));
|
||||
|
||||
if (deviceCount == 0) {
|
||||
printf("FAIL: No HIP devices found!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
hipDeviceProp_t props;
|
||||
HIP_CHECK(hipGetDeviceProperties(&props, 0));
|
||||
printf("OK\n");
|
||||
printf(" Device: %s\n", props.name);
|
||||
printf(" GCN Arch: %s\n", props.gcnArchName);
|
||||
printf(" Compute Units: %d\n", props.multiProcessorCount);
|
||||
printf(" Total Memory: %zu MB (shared system RAM)\n", props.totalGlobalMem / (1024*1024));
|
||||
printf(" Integrated: %s\n", props.integrated ? "YES (APU)" : "NO");
|
||||
printf(" Managed Memory: %s\n", props.managedMemory ? "YES" : "NO");
|
||||
fflush(stdout);
|
||||
|
||||
// Step 2: Allocate MANAGED memory (unified — safe for APU/shared memory)
|
||||
const int N = 1 << 16; // 65536 elements
|
||||
size_t bytes = N * sizeof(float);
|
||||
|
||||
printf("[2/4] Allocating managed memory (%.1f KB x3)... ", bytes/1024.0);
|
||||
fflush(stdout);
|
||||
|
||||
float *A = nullptr, *B = nullptr, *C = nullptr;
|
||||
HIP_CHECK(hipMallocManaged(&A, bytes));
|
||||
HIP_CHECK(hipMallocManaged(&B, bytes));
|
||||
HIP_CHECK(hipMallocManaged(&C, bytes));
|
||||
printf("OK\n");
|
||||
fflush(stdout);
|
||||
|
||||
// Initialize on host (managed memory is accessible from both CPU and GPU)
|
||||
for (int i = 0; i < N; i++) {
|
||||
A[i] = sinf(i) * sinf(i);
|
||||
B[i] = cosf(i) * cosf(i);
|
||||
C[i] = 0.0f;
|
||||
}
|
||||
|
||||
// Step 3: Launch kernel
|
||||
int threadsPerBlock = 256;
|
||||
int blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock;
|
||||
|
||||
printf("[3/4] Launching kernel (%d blocks x %d threads)... ", blocksPerGrid, threadsPerBlock);
|
||||
fflush(stdout);
|
||||
|
||||
hipEvent_t start, stop;
|
||||
HIP_CHECK(hipEventCreate(&start));
|
||||
HIP_CHECK(hipEventCreate(&stop));
|
||||
|
||||
HIP_CHECK(hipEventRecord(start));
|
||||
hipLaunchKernelGGL(vectorAdd, dim3(blocksPerGrid), dim3(threadsPerBlock), 0, 0, A, B, C, N);
|
||||
HIP_CHECK(hipGetLastError());
|
||||
HIP_CHECK(hipEventRecord(stop));
|
||||
HIP_CHECK(hipEventSynchronize(stop));
|
||||
|
||||
float ms = 0;
|
||||
HIP_CHECK(hipEventElapsedTime(&ms, start, stop));
|
||||
printf("OK (%.3f ms)\n", ms);
|
||||
fflush(stdout);
|
||||
|
||||
// Step 4: Verify on host (managed memory — no memcpy needed!)
|
||||
printf("[4/4] Verifying results... ");
|
||||
fflush(stdout);
|
||||
|
||||
// Ensure GPU is done
|
||||
HIP_CHECK(hipDeviceSynchronize());
|
||||
|
||||
int errors = 0;
|
||||
for (int i = 0; i < N; i++) {
|
||||
float expected = A[i] + B[i]; // sin²(x) + cos²(x) = 1.0
|
||||
if (fabsf(C[i] - expected) > 1e-5) {
|
||||
if (errors < 5) {
|
||||
fprintf(stderr, "\n Mismatch at [%d]: got %f, expected %f",
|
||||
i, C[i], expected);
|
||||
}
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors == 0) {
|
||||
printf("PASSED — all %d elements correct (sin²+cos²=1.0)\n", N);
|
||||
} else {
|
||||
printf("FAILED — %d/%d mismatches\n", errors, N);
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
// CRITICAL BC-250 WORKAROUND:
|
||||
// The HIP runtime's static destructors trigger KIQ queue teardown on the
|
||||
// BC-250's shared-memory architecture, causing "timeout waiting for kiq fence"
|
||||
// and a full system hang (no GPU reset possible on shared RAM APU).
|
||||
//
|
||||
// We MUST use _exit() to terminate immediately, bypassing:
|
||||
// - C++ static destructors (HIP runtime cleanup)
|
||||
// - atexit() handlers
|
||||
// - HIP's internal queue teardown via KIQ
|
||||
//
|
||||
// Memory is reclaimed by the OS. The GPU queues are released by KFD
|
||||
// when the process file descriptors are closed, which is safer than
|
||||
// the HIP runtime's explicit teardown path.
|
||||
|
||||
printf("\n=== ROCm HIP Compute: %s ===\n", errors == 0 ? "FULLY OPERATIONAL" : "FAILED");
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
_exit(errors > 0 ? 1 : 0); // HARD EXIT — bypasses HIP destructors
|
||||
}
|
||||
Reference in New Issue
Block a user