CI / Test (macos-latest) (push) Blocked by required conditions
CI / Test (ubuntu-latest) (push) Blocked by required conditions
CI / Build (macos-latest) (push) Waiting to run
CI / Python Bindings (maturin) (macos-latest) (push) Blocked by required conditions
CI / Python Bindings (maturin) (ubuntu-latest) (push) Blocked by required conditions
CI / WASM Build + Size Check (push) Blocked by required conditions
CI / Distributed Training Tests (push) Blocked by required conditions
CI / CI Success (push) Blocked by required conditions
CI / Format Check (push) Failing after 3s
CI / Clippy Check (push) Failing after 4s
CI / Build (ubuntu-latest) (push) Failing after 3s
Performance Benchmarks / Run Benchmarks (push) Failing after 4s
Documentation / Build User Guide (push) Successful in 5s
CI / Build CPU-Only (Explicit) (push) Failing after 1m21s
Documentation / Build API Documentation (push) Failing after 1m29s
Co-Authored-By: Claude Fable 5.1 <[email protected]>
182 lines
6.4 KiB
Plaintext
182 lines
6.4 KiB
Plaintext
/**
|
||
* 3D Stage 1, gate 3: the f64 conjugate gradient's maps on the device over
|
||
* the active cells (index list), with FIXED-ORDER reductions: every block
|
||
* reduces its 256 lanes by the same shared-memory tree and writes one
|
||
* partial; `cg3_reduce` sums the partials in index order on one thread.
|
||
* Run-to-run bit-identical by construction (no atomics).
|
||
*/
|
||
#define NONE 0xFFFFFFFFu
|
||
|
||
__device__ __forceinline__ double nb_sum3d(
|
||
int g, int nx, const double* ae, const double* aw, const double* an, const double* as_,
|
||
const double* at, const double* ab, const unsigned int* top, const unsigned int* bot,
|
||
const double* x)
|
||
{
|
||
double s = 0.0;
|
||
double e = ae[g]; if (e != 0.0) s += e * x[g + 1];
|
||
double w = aw[g]; if (w != 0.0) s += w * x[g - 1];
|
||
double nn = an[g]; if (nn != 0.0) s += nn * x[g + nx];
|
||
double ss = as_[g]; if (ss != 0.0) s += ss * x[g - nx];
|
||
double t = at[g]; if (t != 0.0) s += t * x[top[g]];
|
||
double b = ab[g]; if (b != 0.0) s += b * x[bot[g]];
|
||
return s;
|
||
}
|
||
|
||
__device__ __forceinline__ double block_reduce(double v)
|
||
{
|
||
__shared__ double sh[256];
|
||
int t = threadIdx.x;
|
||
sh[t] = v;
|
||
__syncthreads();
|
||
for (int s = 128; s > 0; s >>= 1) {
|
||
if (t < s) sh[t] += sh[t + s];
|
||
__syncthreads();
|
||
}
|
||
return sh[0];
|
||
}
|
||
|
||
/* q = A d on the cells. */
|
||
extern "C" __global__ void cg3_spmv(
|
||
int n_cells, const unsigned int* __restrict__ cells,
|
||
const double* __restrict__ ae, const double* __restrict__ aw,
|
||
const double* __restrict__ an, const double* __restrict__ as_,
|
||
const double* __restrict__ at, const double* __restrict__ ab,
|
||
const unsigned int* __restrict__ top, const unsigned int* __restrict__ bot,
|
||
const double* __restrict__ ap, const double* __restrict__ d, double* __restrict__ q, int nx)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
if (t >= n_cells) return;
|
||
int g = cells[t];
|
||
q[g] = ap[g] * d[g] - nb_sum3d(g, nx, ae, aw, an, as_, at, ab, top, bot, d);
|
||
}
|
||
|
||
/* r = b − A p on the cells; partial[block] = Σ |r| over the block's cells. */
|
||
extern "C" __global__ void cg3_residual(
|
||
int n_cells, const unsigned int* __restrict__ cells,
|
||
const double* __restrict__ ae, const double* __restrict__ aw,
|
||
const double* __restrict__ an, const double* __restrict__ as_,
|
||
const double* __restrict__ at, const double* __restrict__ ab,
|
||
const unsigned int* __restrict__ top, const unsigned int* __restrict__ bot,
|
||
const double* __restrict__ ap, const double* __restrict__ b,
|
||
const double* __restrict__ p, double* __restrict__ r, double* __restrict__ partial, int nx)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
double v = 0.0;
|
||
if (t < n_cells) {
|
||
int g = cells[t];
|
||
v = b[g] - (ap[g] * p[g] - nb_sum3d(g, nx, ae, aw, an, as_, at, ab, top, bot, p));
|
||
r[g] = v;
|
||
v = fabs(v);
|
||
}
|
||
double s = block_reduce(v);
|
||
if (threadIdx.x == 0) partial[blockIdx.x] = s;
|
||
}
|
||
|
||
/* partial[block] = Σ a·b over the block's cells (b = a for a norm). */
|
||
extern "C" __global__ void cg3_dot_partial(
|
||
int n_cells, const unsigned int* __restrict__ cells,
|
||
const double* __restrict__ a, const double* __restrict__ b, double* __restrict__ partial)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
double v = 0.0;
|
||
if (t < n_cells) { int g = cells[t]; v = a[g] * b[g]; }
|
||
double s = block_reduce(v);
|
||
if (threadIdx.x == 0) partial[blockIdx.x] = s;
|
||
}
|
||
|
||
/* partial[block] = Σ |a| over the block's cells. */
|
||
extern "C" __global__ void cg3_l1_partial(
|
||
int n_cells, const unsigned int* __restrict__ cells,
|
||
const double* __restrict__ a, double* __restrict__ partial)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
double v = 0.0;
|
||
if (t < n_cells) v = fabs(a[cells[t]]);
|
||
double s = block_reduce(v);
|
||
if (threadIdx.x == 0) partial[blockIdx.x] = s;
|
||
}
|
||
|
||
/* partial[block] = Σ a over the block's cells. */
|
||
extern "C" __global__ void cg3_sum_partial(
|
||
int n_cells, const unsigned int* __restrict__ cells,
|
||
const double* __restrict__ a, double* __restrict__ partial)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
double v = 0.0;
|
||
if (t < n_cells) v = a[cells[t]];
|
||
double s = block_reduce(v);
|
||
if (threadIdx.x == 0) partial[blockIdx.x] = s;
|
||
}
|
||
|
||
/* out[0] = Σ partial[0..n) in index order, one thread. */
|
||
extern "C" __global__ void cg3_reduce(int n, const double* __restrict__ partial, double* __restrict__ out)
|
||
{
|
||
if (blockIdx.x * blockDim.x + threadIdx.x != 0) return;
|
||
double s = 0.0;
|
||
for (int i = 0; i < n; ++i) s += partial[i];
|
||
out[0] = s;
|
||
}
|
||
|
||
/* p += alpha d; r -= alpha q. */
|
||
extern "C" __global__ void cg3_axpy2(
|
||
int n_cells, const unsigned int* __restrict__ cells, double alpha,
|
||
const double* __restrict__ d, const double* __restrict__ q,
|
||
double* __restrict__ p, double* __restrict__ r)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
if (t >= n_cells) return;
|
||
int g = cells[t];
|
||
p[g] += alpha * d[g];
|
||
r[g] -= alpha * q[g];
|
||
}
|
||
|
||
/* d = z + beta d. */
|
||
extern "C" __global__ void cg3_xpay(
|
||
int n_cells, const unsigned int* __restrict__ cells, double beta,
|
||
const double* __restrict__ z, double* __restrict__ d)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
if (t >= n_cells) return;
|
||
int g = cells[t];
|
||
d[g] = z[g] + beta * d[g];
|
||
}
|
||
|
||
/* dst = src (copy over the cells). */
|
||
extern "C" __global__ void cg3_copy(
|
||
int n_cells, const unsigned int* __restrict__ cells,
|
||
const double* __restrict__ src, double* __restrict__ dst)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
if (t >= n_cells) return;
|
||
int g = cells[t];
|
||
dst[g] = src[g];
|
||
}
|
||
|
||
/* v -= s over the cells. */
|
||
extern "C" __global__ void cg3_shift(
|
||
int n_cells, const unsigned int* __restrict__ cells, double s, double* __restrict__ v)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
if (t >= n_cells) return;
|
||
v[cells[t]] -= s;
|
||
}
|
||
|
||
/* f32 b0 = (float) r over the cells; f64 z = (double) x0 over the cells. */
|
||
extern "C" __global__ void cg3_gather_f32(
|
||
int n_cells, const unsigned int* __restrict__ cells, const double* __restrict__ r, float* __restrict__ b0)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
if (t >= n_cells) return;
|
||
int g = cells[t];
|
||
b0[g] = (float) r[g];
|
||
}
|
||
|
||
extern "C" __global__ void cg3_scatter_f64(
|
||
int n_cells, const unsigned int* __restrict__ cells, const float* __restrict__ x0, double* __restrict__ z)
|
||
{
|
||
int t = blockIdx.x * blockDim.x + threadIdx.x;
|
||
if (t >= n_cells) return;
|
||
int g = cells[t];
|
||
z[g] = (double) x0[g];
|
||
}
|