nk
1.0.0
C++ Numerical Computing Runtime
Toggle main menu visibility
Loading...
Searching...
No Matches
kernels.hpp
1
// nk/ops/kernels.hpp
2
//
3
// Public raw-buffer compute kernels — the STABLE facade over the backend-split
4
// inner loops (which live in nk::ops::detail and are selected at build time
5
// by NK_WITH_SIMD). Two audiences:
6
//
7
// * the codegen subsystem — generated C++ calls these directly as its
8
// lowering target for heavy array ops (column-major double buffers, the
9
// same RawBuffer ABI the emitter already uses), so a transpiled kernel
10
// reuses ops' SIMD implementation instead of emitting a naive loop; and
11
// * any in-tree caller that already holds raw buffers and wants the fast path
12
// without going through Value.
13
//
14
// Callers use ONLY this header — never nk::ops::detail. This is where the
15
// complex / elementwise / transcendental / fft kernel entries will also land
16
// as the codegen lowering surface grows.
17
#pragma once
18
19
#include <complex>
20
#include <cstddef>
21
22
// Linkage. Default (static — compiled into nk_ops, a test, or a
23
// self-contained artifact): plain. Building the nk_ops_kernels shared lib:
24
// dllexport. A consumer linking that shared lib (a codegen artifact that uses
25
// ops kernels): define NK_OPS_USE_DLL -> dllimport. No effect off Windows.
26
// Mirrors NK_RT_API (nk_codegen_rt.h).
27
#if defined(_WIN32) && defined(NK_OPS_BUILDING_DLL)
28
# define NK_OPS_API __declspec(dllexport)
29
#elif defined(_WIN32) && defined(NK_OPS_USE_DLL)
30
# define NK_OPS_API __declspec(dllimport)
31
#else
32
# define NK_OPS_API
33
#endif
34
35
namespace
nk::ops {
36
37
// C(M×N) = A(M×K) · B(K×N), all column-major (a[k*M+i], b[j*K+k], c[j*M+i]).
38
// C is caller-allocated; the kernel zeroes then accumulates. SIMD MulAdd down
39
// columns of A under NK_WITH_SIMD, a portable loop otherwise.
40
NK_OPS_API
void
matmulDouble(
const
double
*a,
const
double
*b,
double
*c,
41
std::size_t M, std::size_t N, std::size_t K);
42
43
// Same, for complex matrices (column-major std::complex<double>). Portable
44
// SAXPY loop (no SIMD-complex split); the single call is amortised over O(M·N·K)
45
// work, so it carries no per-element overhead vs an inline loop.
46
NK_OPS_API
void
matmulComplex(
const
std::complex<double> *a,
const
std::complex<double> *b,
47
std::complex<double> *c,
48
std::size_t M, std::size_t N, std::size_t K);
49
50
// Element-wise binary ops over two equal-length DOUBLE buffers: out[i] = a[i] OP
51
// b[i], n elements (flat — rank-agnostic). SIMD under NK_WITH_SIMD with an
52
// internal small-N scalar gate (so no dynamic-dispatch crater at tiny n). NOTE:
53
// a plain __restrict inline loop already auto-vectorises to match these for
54
// cheap arithmetic (A3) — codegen uses them only as the opt-in ops-kernel tier;
55
// the inline loop stays the self-contained default.
56
NK_OPS_API
void
plusDouble (
const
double
*a,
const
double
*b,
double
*out, std::size_t n);
57
NK_OPS_API
void
minusDouble (
const
double
*a,
const
double
*b,
double
*out, std::size_t n);
58
NK_OPS_API
void
timesDouble (
const
double
*a,
const
double
*b,
double
*out, std::size_t n);
59
NK_OPS_API
void
rdivideDouble(
const
double
*a,
const
double
*b,
double
*out, std::size_t n);
60
61
// Element-wise transcendentals over a DOUBLE buffer: out[i] = fn(x[i]), n
62
// elements. Forward to the SIMD fusedTransAffine kernel (scale=1, offset=0) —
63
// the SAME vectorised path the runtime's expression fusion uses, so the result
64
// matches the interpreter. A plain std::<fn> inline loop does NOT auto-vectorise
65
// on MSVC, so these are a genuine speedup (unlike the cheap-arithmetic ops). The
66
// set is the real-total transcendentals (no complex-domain decline): the
67
// codegen lowers exactly these inline today and routes them here when opt-in.
68
NK_OPS_API
void
sinDouble (
const
double
*x,
double
*out, std::size_t n);
69
NK_OPS_API
void
cosDouble (
const
double
*x,
double
*out, std::size_t n);
70
NK_OPS_API
void
tanDouble (
const
double
*x,
double
*out, std::size_t n);
71
NK_OPS_API
void
atanDouble (
const
double
*x,
double
*out, std::size_t n);
72
NK_OPS_API
void
sinhDouble (
const
double
*x,
double
*out, std::size_t n);
73
NK_OPS_API
void
coshDouble (
const
double
*x,
double
*out, std::size_t n);
74
NK_OPS_API
void
tanhDouble (
const
double
*x,
double
*out, std::size_t n);
75
NK_OPS_API
void
expDouble (
const
double
*x,
double
*out, std::size_t n);
76
NK_OPS_API
void
asinhDouble(
const
double
*x,
double
*out, std::size_t n);
77
NK_OPS_API
void
expm1Double(
const
double
*x,
double
*out, std::size_t n);
78
79
}
// namespace nk::ops
src
ops
include
nk
ops
kernels.hpp
Generated by
1.17.0