Community post
XAIGPUARC /// WAVEFRONT ATTENTION /// PLUS big UPDATEWORK
//XAC_sycl_spielewiese_ki.cpp
//ALLEINSTELLUNGSFUNKTION
//XAIGPUARC OpenSource MIT LIZENZ
//FROM HERZ WITH HELP OF AI ARCHITEKT alucian Berlin-Buch 01.09.2026 /// 10:42
//Nur F16/(Nebengewicht F32) Ausschliesslich empfohlene Modell in UNTERSTUETZUNG 3 in 1 Kern
//SPEZIALISIERT FUER ARC Intel XE++ iGPU+dGPU TENSOR SPLIT ROW XMX NUTZUNG
//scalar_t* out_row_ptr = out_ptr + (head_row * out_stride);
//XAC ist PRAEFIX fuer XAIGPUARC 128 ASCIII beachten ohne Umlaute und scharfem S
//Grossschreibung bevorzugt Zeichenhaltung einfach Nummerierung MAXIMUM 10 Punkte
//RICHTIG FALSCH RICHTIG RUECKFALLMECHANISMUS EINBAUEN FUER joint_matrix_mad(sg, mat_s, mat_q, mat_k, mat_s);
//CODENAME: SPIELEWIESE KI aka " SANDKASTEN ATTENTION " ERSTLINGSWERK KI KERNBAU NACH OPENCL ARC GPU ZHASH MINING PROGRAMMBAU
//XMX SKALAR Softmax (Vor!implementiert)
//joint_matrix_mad (Q×K^T) (implementiert)
//joint_matrix_mad (S×V) (implementiert)
//scalar RUECKFALLKERNE (implementiert)
//XAC_sycl_dot_product_vec (vektorisiert implementiert)
//V-Multiplikation (implementiert)
//ATTENTION // ACHTEN IN VERSETZTER FORM ZUERST DIE MARKIERUNG DER 10 ZEHN HAUPTFUNKTIONSABSCHNITTE DANN RECHTS DIE SEKUNDAERABSCHNITTE
0.HILFSFUNKTIONEN // SPIELEWIESE KI RUECKFALLRUECKFALLAUTOMATISIMUSGENERALRUNDIERUNGSACHTUNGSMATRIZENMODUS KLEINSTAUFGABENSPACHMODELL
//KernIdentifikation:
//Geheimspielsplatzsandkastensprachmodellverortungsidentifikation
//IndexAnpassung:
//Stellt die BAUGRUNDLAGE FUER XAIGPUARC ALS STANDALONE ALLEINSTELLUNGSKERN DAR UND ERGIBT IN SUMME
//ALLE GROSSEN KERNE IN MINIMALFUNKTION SPEZIELL AUF EIN MODELL OPTIMIERT FUER
//WENIGE ABER MASSENHAFT UND SCHNELLE AUFGABEN WIE EINFACHE RECHNUNGEN ODER UEBERSETZTUNGEN ZU
//ERSTELLEN SOWIE CODESCHNIPSEL ZU TESTEN UND ZU BAUEN
//DIESER KERN BEZIEHUNGSWEISE DIE MASSE SEINER UNTER UND NACH DEM XAIGPUARC_Datei_Index GERICHTETEN
//UNTERKERNEN FUNKTIONIERT AUS SICH SELBST HERAUS UNTER DEN GETESTETEN BEDINGUNGEN BEI ERFOLG IMMER
//UND GLEICH IM ERGEBNIS. SEINE FUNKTIONEN SIND ENORM EINGESCHRAENKT ABER IM GEBRAUCH FUER
//EINEN GEWISSEN ZWECK HOCHGRADIG OPTIMIERT UND GETESTET.
//DIESER BAU STELL LEDIGLICHE EINE FERTIGSTELLUNG VON BEREITS ERREICHTEN UND VALDIERTEN ERGEBNISSEN
//MIT EINEM EHEMALIGEM FORK VON LLAMA CPP DAR UND WIRD BIS ZU SEINER VOLLENDUNG GEHEGT UND GEPFLEGT.
//DER VORGANG ENTSPRICHT ZU ERSTEINMAL DIESE FOLGENDEN ANSTENDEN PUNKTE AB HIER 1 bis 10 ORDENTLICH
//IN DIE RICHTIGE ZEILE EINUFUEGEN!!! PRIORI EINS!!!
1. XAC_sycl_api_attention_qkv
//KernIdentifikation:
//Aeußeres SYCLZugangsfenster für die QKVKommunikation.
//IndexAnpassung:
//Entspricht der SchnittstellenDefinition im Bereich kernels/ und bindet sauber an die DispatchEbene an.
2. XAC_sycl_dot_product_vec
//KernIdentifikation:
//Vektoriertes Skalarprodukt (F16/F32 Optimierung).
//IndexAnpassung:
//Uebergang in die VektorKernbibliothek (XAC_sycl_flash_attention_vec.h/.cpp).
3. XAC_sycl_flash_attention_vec_scl
//KernIdentifikation:
//Skalarer FallbackPunktproduktautomat fuer Flash Attention.
//IndexAnpassung:
//Abgleich mit dem Pfad kernels/XAC_sycl_flash_attention_scl.cpp.
4. XAC_sycl_xmx_matrix_ops_impl
//KernIdentifikation:
//XMXHardwareMatrixoperationen (SubGroups / Intel Arc).
//IndexAnpassung:
//Ausrichtung an kernels/XAC_sycl_xmx_matrix_ops_scl.h.
5. XAC_sycl_flash_attention_vec_impl
//KernIdentifikation:
//Punktproduktorchestrierung automatisiert für Vektorpfade.
//IndexAnpassung:
//Exakte Entsprechung zu XAC_sycl_flash_attention_vec im Sandbox und KernelVerzeichnis.
6. XAC_sycl_wavefront_optimized_attention
//KernIdentifikation:
//Wavefrontfreundliche Reduktion ueber Intel Arc SubGroups Größe 16.
//IndexAnpassung:
//Wandert direkt in die Hardwarenahen XMXOptimierungen unter kernels/XAC_sycl_xmx_matrix_ops_vec.cpp.
7. XAC_sycl_xmx_matrix_ops_scl
//KernIdentifikation:
//Skalierter XMXKernmischpultUebersetzer mit SoftmaxIntegration.
//IndexAnpassung:
//Zugeordnet zum Modul XAC_sycl_xmx_matrix_ops_scl.
8. XAC_sycl_validate_attention_params
//KernIdentifikation:
//Parameter und Typenpruefung F16/F32 Alignment.
//IndexAnpassung:
//Zentralisiert in den Parser und CommonHilfsstrukturen common/.
9. XAC_sycl_load_to_slm_attention Lambda
//Kern Identifikation: Shared Local Memory (SLM) CacheOptimierung fuer maximale Speicherbandbreite.
//IndexAnpassung:
//Verankert im USM-Speichermanagement XAC_unified_memory_manager.cpp.
10. main
//KernIdentifikation: Gerätererkennung, Allokation und TestInferenz der Spielewiese KI.
//IndexAnpassung:
//Fuehrt als Initialisierung über src/main.cpp und sandbox/XAC_sycl_spielewiese_ki.cpp alle Fäden zusammen.
//StrukturAbgleich Index-Datei
//Damit nach aussen hin alles lueckenlos XAIGPUARC_Datei_Index.txt passt, greifen die Funktionskerne nun greifbar in folgende Ordner greifen:
//Sandbox / Spielwiese:
//include/xaigpuarc/sandbox/XAC_sycl_spielewiese_ki.h
//Kerne: src/kernels/XAC_sycl_flash_attention_vec.cpp & XAC_sycl_xmx_matrix_ops_scl
//Spezifische 10 Stationen Detail finalen Header Abgleich umschreiben
#include <cstdlib>
#include <cmath>
#include <fstream>
#include <iostream>
#include <vector>
#include <chrono>
#include <limits>
#include <cstdio>
#include <sycl/sycl.hpp>
#include <sycl/ext/intel/math.hpp>
#include <sycl/ext/oneapi/experimental/matrix/matrix.hpp>
//KOPZEILENUMGEBUNG DER MATRIX MATRIZEN PARSER
#include "XAIGPUARC/include/XAC_parser.h"
#include "XAIGPUARC/include/XAC_alloc_parser.h"
#include "XAIGPUARC/include/XAC_impl_parser.h"
#include "XAIGPUARC/include/XAC_sycl_parser.h"
#include <XAIGPUARC/include/XAC_sycl_f16_parser.h>
typedef struct XAC_Tensor {
void* XAC_DATA_F16;//INKLUDIERE XAC_DATA_F16/F32
int XAC_TYPE_F16; // INKLUDIERE XAC_TYPE_F16/F32
int ne[4];
int nb[4];
void* backend;
} XAC_Tensor;
typedef struct XAC_backend_sycl_context {
sycl::queue* queue;
} XAC_backend_sycl_context;
//TYPDEFINITIONEN
#define XAC_TYPE_F16 0
#define XAC_TYPE_F32 1
#define XAC_D_MAX 1024
#define XAC_VEC_SIZE 16
#define XAC_WG_SIZE 16
#define XAC_BLOCK_M 128
#define XAC_BLOCK_N 128
#define XAC_MEM_ALIGN 128
//LOGIN INFORMATIONEN MIKROVERSIONEN
#ifndef XAC_LOG_ERROR
#define XAC_LOG_ERROR(msg) std::cerr << "ERROR ACHTUNG FEHLER NEUINSTALLTATION DER SPIELEWIESE KI NOTWENDIG PRUEFE ABHAENGIGKEITEN" << msg << std::endl
#endif
#ifndef XAC_LOG_WARN
#define XAC_LOG_WARN(msg) std::cerr << "WARNUNG ACHTUNG PROGRAMM WIRD NICHT IM OPTIMALEM MODUS AUSGEFUEHRT BITTE PRUEFEN SIE IHRE HARDWAREABHAENGIGKEITEN" << msg << std::endl
#endif
#ifndef XAC_LOG_INFO
#define XAC_LOG_INFO(msg) std::cout << "[INFORMATIONSDATENBANK] " << msg << std::endl
#endif
#ifndef XAC_LOG_ABORT
#define XAC_LOG_ABORT(msg) { std::cerr << "ABBRUCH XAIGPUARC SPIELEWIESE KI KONNTE NICHT GESTARTET WERDEN NEUSTART VERSUCHEN" << msg << std::endl; std::exit(1); }
#endif
//#include "XAC_attention_qkv.h"
namespace XAC {
//0 ATTENTION HILFFUNKTIONEN Skalares Punktprodukt Fallback
template <typename T>
inline float xac_dot_product_scl(float* q,T* k, int d) {
float score = 0.0f;
for (int i = 0; i < d; ++i) {
float final_score += q[i] * static_cast<float>(k[i]);
}
return float final_score;
}
inline bool XAC_sycl_validate_attention_params(XAC_Tensor* q, XAC_Tensor* k) {
if (q->XAC_TYPE_F16 != XAC_TYPE_F16 && q->XAC_TYPE_F16 != XAC_TYPE_F32) {
XAC_LOG_ERROR("NICHT UNTERSTUETZTER DATENTYP");
}
if (q->XAC_TYPE_F16 != k->XAC_TYPE_F16) {
XAC_LOG_ERROR("QUERY UND KEY MUESSEN GLEICHEN TYP HABEN");
return false;
}
return true;
}
} // namespace XAC
//SKALARRUECKFALLMECHNISMUS
template <typename T>
void XAC_sycl_flash_attention_fallback(
T* q,
T* k,
T* v,
T* out,
int num_q,
int num_k,
int d_k,
int d_v,
int q_stride,
int k_stride,
int v_stride,
int out_stride,
sycl::nd_item<1> item
)
) {
// Implementation
}
//XMXKernel
template <typename T>
void XAC_sycl_xmx_matrix_ops_scl(
T* q,
T* k,
T* v,
T* out,
int num_q,
int num_k,
int d_k,
int d_v,
int q_stride,
int k_stride,
int v_stride,
int out_stride,
sycl::nd_item<1> item
) {
//XMXImplementation
}
//Vektorisierter XMXKernel
template <typename T>
void XAC_sycl_xmx_matrix_ops_vec(
T* q,
T* k,
T* v,
T* out,
int num_q,
int num_k,
int d_k,
int d_v,
int q_stride,
int k_stride,
int v_stride,
int out_stride,
sycl::nd_item<1> item
) {
// Vektorisierte XMXImplementation
}
} // namespace XAC
/**
* @brief VEKTORISIERTES PUNKT PRODUKT ZWISCHEN "q[i]" UND "k[j]"
* @tparam const scalar_t, 16> vec; scalar_t DATENTYP sycl::half ODER FLIESSWERTE
* @param q_row_float QUERY ZEILE ALS FLIESSWERTE
* @param k_ptr SCHLUESSELPUNKTE UND ZEIGER
* @param d_k KOPFDIMENSIONEN DER MATRIZENLOGIK
* @return PUNKTPRODUKTAUTOMATITION ALS FLIESSWERTE
*/
using namespace sycl;
using namespace sycl::ext::oneapi::experimental::matrix;
//1 ATTENTION API ZUGANGSFENSTER FUER AUSSENKOMMUNIKATION111111111111111111111111
inline sycl::half* get_ptr(
XAC_Tensor* XAC_Tensor) {
return reinterpret_cast<sycl::half*>(XAC_Tensor->XAC_DATA_F16);
extern "C"
void XAC_sycl_api_attention_qkv(
XAC_sycl_context* ctx,
XAC_Tensor* dst,
//VALIDIERUNG
bool
XAC_sycl_validate_attention_params
XAC_Tensor* q,
XAC_Tensor* k,
XAC_Tensor* v,
int& d_k,
int& d_v) {
if (q->XAC_TYPE_F16
!= XAC_TYPE_F16 && q->
XAC_TYPE_F32 != XAC_TYPE_F32) {
XAC_LOG_ERROR("NUR F16 und F32 unterstuetzt");
return false;
}
if (q->XAC_TYPE_F16 != k->XAC_TYPE_F16 || q->XAC_TYPE_F16 != v->XAC_TYPE_F16) {
XAC_LOG_ERROR("ALLE TENSOREN XAC_TYPE_F16 MUESSEN GLEICHEN TYP HABEN");
return false;
}
d_k = q->ne[0];
d_v = v->ne[0];
if (d_k != k->ne[0] || d_v != v->ne[0]) {
XAC_LOG_ERROR("DIMENSIONSKONSISTENZ FEHLER");
return false;
}
if (d_k > XAC_D_MAX || d_v > XAC_D_MAX) {
XAC_LOG_ERROR("DIMENSIONEN UEBERSCHREITEN MAXIMUM");
return false;
}
if (d_k % XAC_VEC_SIZE != 0 || d_v % XAC_VEC_SIZE != 0) {
XAC_LOG_WARN("SUBOPTIMALE DIMENSIONEN FUER VEKTORISIERUNG");
}
return true;
}
) {
if (!XAC::XAC_sycl_validate_attention_params(q, k)) {
return;
}
sycl::queue& queue = *(ctx->queue);
bool has_xmx = queue.get_device().has(sycl::aspect::ext_intel_matrix);
//DIMENSIONEN EXTRAHIEREN
int num_q = q->ne[1];
int num_k = k->ne[1];
int d_k = k->ne[0];
int d_v = v->ne[0];
auto* q_data = reinterpret_cast<sycl::half*>(q->XAC_DATA_F16);
auto* k_data = reinterpret_cast<sycl::half*>(k->XAC_DATA_F16);
auto* v_data = reinterpret_cast<sycl::half*>(v->XAC_DATA_F16);
auto* out_data = reinterpret_cast<sycl::half*>(dst->XAC_DATA_F16);
bool can_use_xmx = has_xmx && (d_k % 16 == 0) && (d_v % 16 == 0);
queue.submit([&](sycl::handler& h) {
if (can_use_xmx) {
h.parallel_for<class XAC_XMX_Kernel>(
sycl::nd_range<1>(
sycl::range<1>(((num_q + 15) / 16) * 16),
sycl::range<1>(16)
),
[=](sycl::nd_item<1> item)
[[intel::reqd_sub_group_size(16)]] {
XAC_sycl_kernel_flash_attention_xmx(
q_data, k_data, v_data, out_data,
num_q, num_k, d_k, d_v,
q->nb[1] / sizeof(sycl::half),
k->nb[1] / sizeof(sycl::half),
v->nb[0] / sizeof(sycl::half),
dst->nb[0] / sizeof(sycl::half),
item
);
}
);
} else {
h.parallel_for<class XAC_Fallback_Kernel>(
sycl::nd_range<1>(
sycl::range<1>(num_q * XAC_WORKGROUP_SIZE),
sycl::range<1>(XAC_WORKGROUP_SIZE)
),
[=](sycl::nd_item<1> item) {
XAC::xac_flash_attention_fallback(
q_data, k_data, v_data, out_data,
num_q, num_k, d_k, d_v,
q->nb[1] / sizeof(sycl::half),
k->nb[1] / sizeof(sycl::half),
v->nb[0] / sizeof(sycl::half),
dst->nb[0] / sizeof(sycl::half),
item
);
}
);
}
}).wait();
}
//2 ATTENTION XAC_DOT FUNKTION PUNKTPRODUKT VECTORAUTOMATION PLUS IMPLEMENTIERUNG222222222222222222222
template <typename scalar_t>
inline float XAC_sycl_dot_product_vec(float* q_row_float, scalar_t* k_ptr, int d_k) {
float final_score = 0.0f;
float accum_den = 0.0f;
running_max = -std::numeric_limits<float>::infinity();
float s_scores[XAC_BLOCK_N];
if constexpr (std::is_same_v<scalar_t, sycl::half>) {
if (d_k % XAC_VEC_SIZE != 0) {
for (
int di = 0; di < d_k; ++di) {
final_score += q_row_float[di] * static_cast<float>(k_ptr[di]);
}
return final_score;
}
constexpr
int vec_elements = XAC_VEC_SIZE;
using vec_half = sycl::vec<sycl::half, vec_elements>;
using sycl::vec_float = sycl::vec<
float, vec_elements>;
int sycl::vec_iters = d_k / vec_elements;
for (
int v = 0; v < sycl::vec_iters; ++v) {
vec_half k_half_vec;
k_half_vec.loadv * vec_elements, k_ptr);
sycl::vec_float k_float_vec = k_half_vec.template convert<float>();
sycl::vec_float q_float_vec;
sycl::q_float_vec.sycl::vec.load(v * vec_elements, q_row_float);
final_score += sycl::dot(q_float_vec, k_float_vec);
}
} else {
for (
int di = 0; di < d_k; ++di) {
final_score += q_row_float[di] * static_cast<
float>(k_ptr[di]);
}
}
return final_score;
}
//FAKEDREI 3 VERKTORISIERTES PUNKTPRODUKTAUTOMATIONSRUECKFALLAUTOMATIK
template <typename scalar_t>
inline float XAC_sycl_dot_product_vec(float* q_row_float, scalar_t* k_ptr, int d_k) {
float final_score = 0.0f;
//XAC Vectorpfad bei Ausrichtung : Dimension sowie F16
if constexpr (std::is_same_v<scalar_t, sycl::half>) {
if (d_k % XAC_VEC_SIZE != 0) {
for (int di = 0; di < d_k; ++di) {
float final_score += q_row_float[di] * static_cast<float>(k_ptr[di]);
}
return float final_score;
}
constexpr int vec_elements = XAC_VEC_SIZE;
using vec_half = sycl::vec<sycl::half, vec_elements>;
using sycl::vec_float = sycl::vec<float, vec_elements>;
int sycl::vec_iters = d_k / vec_elements;
for (int v = 0; v < sycl::vec_iters; ++v) {
vec_half k_half_vec;
k_half_vec.loadv * vec_elements, k_ptr);
sycl::vec_float k_float_vec = k_half_vec.template convert<float>();
sycl::vec_float q_float_vec;
sycl::q_float_vec.sycl::vec.load(v * vec_elements, q_row_float);
final_score += sycl::dot(q_float_vec, k_float_vec);
}
return float final_score;
} else {
for (int di = 0; di < d_k; ++di) {
float final_score += q_row_float[di] * k_ptr[di];
}
return float final_score;
}
}
//FINALER FLUESSMATRIZENWERT
/**
* @brief XAC HAUPTKERN AUFDROESSELSTRATEGIE MIT TREFFERWERTEZWISCHENSPEICHER
* @tparam const scalar_t, 16> vec; scalar_t DATENTYP FORMAT INTEL sycl::half HALBE GENAUIGKEIT F16
*/
#endif // XAC_SYCL_SPIELEWIESE_KI_H // CODENAME SPIELEWIESE KI aka " SANDKASTEN ATTENTION "
//3 ATTENTION SKALARRUECKFALLPUNKTPRODUKTAUTOMATION3333333333333333333333333
template <typename
scalar_t>
void XAC_sycl_flash_attention_vec_impl(
sycl::vec<T, 16>,
scalar_t* k_ptr,
scalar_t* v_ptr,
scalar_t* out_ptr,
int num_q,
int num_k,
int d_k,
int d_v,
int q_stride,
int k_stride,
int v_stride,
int out_stride,
sycl::nd_item<1> item
) {
int head_row = item.get_global_id(0);
if (head_row >= num_q) return;
float accum_den = 0.0f;
running_max = -std::numeric_limits<float>::infinity();
float accum_num[XAC_D_MAX] = {0.0f};
float s_scores[XAC_BLOCK_N];
scalar_t* q_row_ptr = q_ptr + head_row * q_stride;
float q_row_float[XAC_D_MAX];
for (
int di = 0; di < d_k; ++di) {
q_row_float[di] = static_cast<
float>(q_row_ptr[di]);
}
sycl::
float scale_factor = 1.0f / sycl::sqrt(static_cast<
float>(d_k));
for (
int k_start = 0; k_start < num_k; k_start += XAC_BLOCK_N) {
int k_block_size = sycl::min(XAC_BLOCK_N, num_k - k_start);
float current_block_max =
running_max;
for (
int kk = 0; kk < k_block_size; ++kk) {
int k_idx = k_start + kk;
scalar_t* k_block_ptr = k_ptr + k_idx * k_stride;
float score = XAC_sycl_dot_product_vec(q_row_float, k_block_ptr, d_k);
score *= sycl::
float scale_factor;
s_scores[kk] = score;
current_block_max = sycl::max(current_block_max, score);
}
if (
running_max != current_block_max) {
sycl::
float scale = sycl::exp(
running_max - current_block_max);
accum_den *= scale;
for (
int vi = 0; vi < d_v; ++vi) {
accum_num[vi] *= scale;
}
running_max = -std::numeric_limits<float>::infinity();
}
for (int kk = 0; kk < k_block_size; ++kk) {
int k_idx = k_start + kk;
sycl::float score = s_scores[kk];
float exp_val = sycl::exp(score = - std::numeric_limits<float>sycl::infinity();
running_max);
accum_den += exp_val;
scalar_t* v_block_ptr = v_ptr + k_idx * v_stride;
for (int vi = 0; vi < d_v; ++vi) {
accum_num[vi] += exp_val * static_cast<
float>(v_block_ptr[vi]);
}
}
}
scalar_t* out_row_ptr = out_ptr + head_row * out_stride;
if (accum_den == 0.0f) {
for (int vi = 0; vi < d_v; ++vi) {
out_row_ptr[vi] = scalar_t(0.0f);
}
return;
}
float inv_den = 1.0f / accum_den;
for (int vi = 0; vi < d_v; ++vi) {
out_row_ptr[vi] = static_cast<scalar_t>(accum_num[vi] * inv_den);
}
}
//4 ATTENTION XMX RUECKFALLPUNKTPRODUKTAUTOMATION44444444444444444444????????
template <typename scalar_t>
void XAC_sycl_flash_attention_kernel_impl_scl( /// DOPPELT OPENBEREICHSABGLEICH
scalar_t* q_ptr,
scalar_t* k_ptr,
scalar_t* v_ptr,
scalar_t* out_ptr,
int num_q,
int num_k,
int d_k,
int d_v,
int q_stride,
int k_stride,
int v_stride,
int out_stride,
sycl::nd_item<1> item
) {
sycl::sub_group sg = item.get_sub_group();//WEG FALLS FALSCH
int head_row_base = item.get_group(0) * 16;
if (head_row_base >= num_q) return;
using t_q = sycl::joint_matrix<sycl::sub_group, sycl::half, use::a, 16, 16, layout::row_major>;
using t_k = sycl::joint_matrix<sycl::sub_group, sycl::half, use::b, 16, 16, layout::row_major>;
using t_acc = sycl::joint_matrix<sycl::sub_group, float, use::sycl::accumulator, 16, 16>;
t_q mat_q;
t_k mat_k;
t_acc mat_s;
sycl::joint_matrix_fill(sg, mat_s, 0.0f);
scalar_t* sycl::q_tile_ptr = q_ptr + head_row_base * q_stride;
joint_matrix_load(sg, mat_q, sycl::q_tile_ptr, q_stride);
float scale_factor = 1.0f / sycl::sqrt((float)d_k);
for (int k_idx = 0; k_idx < num_k; k_idx += 16) {
scalar_t* k_tile_ptr = k_ptr + k_idx * k_stride;
joint_matrix_load(sg, mat_k, k_tile_ptr, k_stride);
//joint_matrix_mad Aufruf Akkumulator
joint_matrix_mad(sg, mat_s, mat_q, mat_k, mat_s);
template <typename scalar_t>
inline float XAC_sycl_dot_product_vec(sycl::vec<dot, scalar_t, 16> vec; float* q_row_float, scalar_t* k_ptr, int d_k) {
float final_score = 0.0f;
if constexpr (std::is_same_v<scalar_t, sycl::half>) {
if (d_k % XAC_VEC_SIZE != 0) {
for (int di = 0; di < d_k; ++di) {
final_score += q_row_float[di] * static_cast<float>(k_ptr[di]);
}
return final_score;
}
constexpr int vec_elements = XAC_VEC_SIZE;
using vec_half = sycl::vec<sycl::half, vec_elements>;
using sycl::vec_float = sycl::vec<float, vec_elements>;
int sycl::vec_iters = d_k / vec_elements;
for (int v = 0; v < sycl::vec_iters; ++v) {
vec_half k_half_vec;
k_half_vec.loadv * vec_elements, k_ptr);
sycl::vec_float k_float_vec = k_half_vec.template convert<float>();
sycl::vec_float q_float_vec;
sycl::q_float_vec.sycl::vec.load(v * vec_elements, q_row_float);
final_score += sycl::dot(q_float_vec, k_float_vec);
}
} else {
for (int di = 0; di < d_k; ++di) {
final_score += q_row_float[di] * static_cast<float>(k_ptr[di]);
}
}
return final_score;
}
}
//SOFTMAX MIT V * NEHMEN FUER ZIELPUNKTIERUNG ATTENTION
template <typename scalar_t>
void XAC_sycl_xmx_matrix_ops_impl(...) {
//aXMX MatrixMultiplikation (Q × K^T) SKALAR RUECKFALLMECHNISMUS
joint_matrix_mad(sg, mat_s, mat_q, mat_k, mat_s);
template <typename scalar_t>
void XAC_sycl_flash_attention_vec_impl(
sycl::vec<T, 16>,
scalar_t* k_ptr,
scalar_t* v_ptr,
scalar_t* out_ptr,
int num_q,
int num_k,
int d_k,
int d_v,
int q_stride,
int k_stride,
int v_stride,
int out_stride,
sycl::nd_item<1> item
) {
int head_row = item.get_global_id(0);
if (head_row >= num_q) return;
float accum_den = 0.0f;
running_max = -std::numeric_limits<float>::infinity();
float accum_num[XAC_D_MAX] = {0.0f};
float s_scores[XAC_BLOCK_N];
scalar_t* q_row_ptr = q_ptr + head_row * q_stride;
float q_row_float[XAC_D_MAX];
for (int di = 0; di < d_k; ++di) {
q_row_float[di] = static_cast<float>(q_row_ptr[di]);
}
float scale_factor = 1.0f / sycl::sqrt((float)d_k);
for (int k_start = 0; k_start < num_k; k_start += XAC_BLOCK_N) {
int k_block_size = sycl::min(XAC_BLOCK_N, num_k - k_start);
running_max = -std::numeric_limits<float>::infinity();
//bSkalierung (1/√d_k) PRO BLOCK SCORE WERT
for (int kk = 0; kk < k_block_size; ++kk) {
int k_idx = k_start + kk;
scalar_t* k_block_ptr = k_ptr + k_idx * k_stride;
float score = XAC_sycl_dot_product_vec(q_row_float, k_block_ptr, d_k);
score *= float scale_factor;
s_scores[kk] = score;
current_block_max = sycl::max(current_block_max, score);
}
//cSoftmax XMX ueber SubGroups Untergruppen
if (running_max != current_block_max) {
float scale = sycl::exp(running_max - current_block_max);
accum_den *= scale;
for (int vi = 0; vi < d_v; ++vi) {
accum_num[vi] *= scale;
}
running_max = -std::numeric_limits<float>::infinity();
}
//dMatrix Multiplikation mat_s × V
for (int kk = 0; kk < k_block_size; ++kk) {
int k_idx = k_start + kk;
float exp_val = sycl::exp(s_scores[kk] - running_max);
accum_den += exp_val;
scalar_t* v_block_ptr = v_ptr + k_idx * v_stride;
for (int vi = 0; vi < d_v; ++vi) {
accum_num[vi] += exp_val * static_cast<float>(v_block_ptr[vi]);
}
}
}
//eErgebnis Speichern
scalar_t* out_row_ptr = out_ptr + head_row * out_stride;
if (accum_den == 0.0f) {
for (int vi = 0; vi < d_v; ++vi) {
out_row_ptr[vi] = scalar_t(0.0f);
}
return;
}
float inv_den = 1.0f / accum_den;
for (int vi = 0; vi < d_v; ++vi) {
out_row_ptr[vi] = static_cast<scalar_t>(accum_num[vi] * inv_den);
joint_matrix_store(sg, mat_s, out_ptr + head_row_base * out_stride, out_stride, layout::row_major);
}
//4444444444Ende
//5 XAC_sycl_flash_attention_vec_impl - ORCHESTRIERUNG
//5 ATTENTION PUNKTPRODUKTORCHESTRATIONSAUTOMATIK55555555555555555
extern "C" void XAC_sycl_flash_attention_vec_impl(
XAC_backend_sycl_context* ctx,
XAC_Tensor* dst,
XAC_Tensor* q_tensor,
XAC_Tensor* k_tensor,
XAC_Tensor* v_tensor,
XAC_Tensor* sycl::mask
) {
if (q_tensor->XAC_TYPE_F32 != XAC_TYPE_F16 && q_tensor->XAC_TYPE_F16 != XAC_TYPE_F32) {
XAC_ABORT("XAC_sycl_flash_attention: Ausschliesslich F16/F32 unterstuetzt");
return;
}
queue& sycl_queue = *(ctx->queue);
bool has_xmx = sycl_queue.get_device().has(sycl::aspect::ext_intel_matrix);
int num_q = q_tensor->ne[1];
int num_k = k_tensor->ne[1];
int d_k = k_tensor->ne[0];
int d_v = v_tensor->ne[0];
int q_stride = q_tensor->nb[1] / sizeof(sycl::half);
int k_stride = k_tensor->nb[1] / sizeof(sycl::half);
int v_stride = v_tensor->nb[1] / sizeof(sycl::half);
int out_stride = dst->nb[1] / sizeof(sycl::half);
sycl::half* q_data = reinterpret_cast<sycl::half*>(q_tensor->XAC_DATA_F16);
sycl::half* k_data = reinterpret_cast<sycl::half*>(k_tensor->XAC_DATA_F16);
sycl::half* v_data = reinterpret_cast<sycl::half*>(v_tensor->XAC_DATA_F16);
sycl::half* out_data = reinterpret_cast<sycl::half*>(dst->XAC_DATA_F16);
//Rueckfallmechanismus XMX Hardware 16er Alignment FALLBACK VECTORISIERT
bool can_use_xmx = has_xmx && (d_k % 16 == 0) && (d_v % 16 == 0);
queue.submit([&](sycl::handler& h) {
if (can_use_xmx) {
h.parallel_for<class XAC_XMX_Kernel>(
sycl::nd_range<1>(sycl::range<1>((num_q + 15) / 16 * 16), sycl::range<1>(16)),
[=](sycl::nd_item<1> item) [[intel::reqd_sub_group_size(16)]] {
XAC_sycl_xmx_matrix_ops_impl(
q_data, k_data, v_data, out_data,
num_q, num_k, d_k, d_v,
q_stride, k_stride, v_stride, out_stride,
item
);
}
);
} else {
h.parallel_for<class XAC_Scalar_Kernel>(
sycl::nd_range<1>(sycl::range<1>(num_q * XAC_WG_SIZE), sycl::range<1>(XAC_WG_SIZE)),
[=](sycl::nd_item<1> item) {
XAC_sycl_flash_attention_vec_impl(
q_data, k_data, v_data, out_data,
num_q, num_k, d_k, d_v,
q_stride, k_stride, v_stride, out_stride,
item
);
}
);
}
}).wait();
}
//VALIDIERT DE
//ZWISCHEN ORCHESTRATOR ALTER SCHULE GRUNDBAUMECHANIK ATTENTION FUER
//XMX KERN UMGEBUNGSVORBAU MIT sycl::sub_group sycl::joint_matrix
//PRIORITAET 1 bis 3 Orchestrator, XMX-Kernel, Vektor Fallback
extern "C" void XAC_sycl_xmx_matrix_ops_vec(queue& q, sycl::half* out, sycl::half* o_ptr, sycl::half* k, sycl::half* v, int num_q, int d_k) {
bool has_xmx = sycl_q.get_device().has(sycl::aspect::ext_intel_matrix);
if (has_xmx && (d_k % 16 == 0)) {
q.parallel_for(sycl::nd_range<1>(sycl::range<1>((num_q + 16) / 16 * 32), sycl::range<1>(32)),
[=](sycl::nd_item<1> item) { [[intel::reqd_sub_group_size(16)]] {
sycl::sub_group sg = item.get_sub_group();
//Neue Untergruppenberechnungen
int sg_size = sg.get_local_range()[0]; // Typisch 16 auf Intel
int sg_id = sg.get_group_id()[0];
int local_id = sg.get_local_id()[0];
//Daten Wavefronts Auslastung
//Jede Sub Group arbeitet in einem zusammenhaengendem Block
int tiles_per_sg = 4; //Jede Sub Group Untergruppe bearbeitet 4 Tiles.
//Diese widerum koennen auch in nocheinmal
//vier untergruppen unter bestimmten bedingungen auf arc eingteilt werden.
constexpr int XAC_TILE_SIZE = 16; //DEFINIEREN
for (int t = 0; t < tiles_per_sg; ++t) {
int tile_offset = (sg_id * tiles_per_sg + t) * XAC_TILE_SIZE;
//VECTORISIERTE SPEICHERBANDBREITENMAXIMIERUNGSAUTOMATIK
scalar_t, 16> vec_data;
vec_data.sycl::vec.load(tile_offset, ptr);
}
//6 TEST 666 ATTENTION OPTIMIERTE SUB GROUP UNTERGRUPPEN XAC_sycl_wavefront_optimized_attention
//NUTZUNG INTEL ARC6666666666666666666666666666666666666666666666666666
template<typename T>
void XAC_sycl_wavefront_optimized_attention(
queue& q,
T* q_ptr,
T* k_ptr,
T* out_ptr,
int num_q,
int d_k
) {
constexpr int SG_SIZE = 16; // Intel ARC Wavefront Groesse
constexpr int TILE_M = 16;
constexpr int TILE_N = 16;
q.parallel_for(
sycl::nd_range<1>(
sycl::range<1>(((num_q + TILE_M - 1) / TILE_M) * SG_SIZE),
sycl::range<1>(SG_SIZE)
),
[=](sycl::nd_item<1> item)
[[intel::reqd_sub_group_size(SG_SIZE)]] {
auto sg = item.get_sub_group();
//JEDE SUB GROUP UNTERGRUPPE BEARBEITET EINE ZEILE
int row = item.get_group(0) * TILE_M + sg.get_local_id()[0];
if (row >= num_q) return;
//LADE VERCTORISIERTE WELLENFRONT WAVEFRONT ARC INTEL CPU IGPUdPUG FREUNDLICH
sycl::vec<T, 16> q_vec;
q_vec.sycl::vec.load(row * d_k, q_ptr);
//RUDKTION UEBER SUB GROUP UNTERGRUPPENREDUZIERUNGSAUTOMATIK
float partial_sum = 0.0f;
#pragma unroll
for (int i = 0; i < 16; ++i) {
partial_sum += static_cast<float>(q_vec[i]) *
static_cast<float>(k_ptr[i]);
}
//SUB GROUP UNTERGRUPPEN REDUKTRION WAVEFRONT OPTIMIERT
float total = sycl::reduce_over_group(
sg, partial_sum, sycl::plus<>()
);
//RESULTAT UNTERGRUPPENFRONTWELLENREDUKTIONSAUTOMATIK SPEICHERN
out_ptr[row] = static_cast<T>(total);
}
).wait();
}
//ABSCHLUSS WELLENFORMATIONFRONTALBRUCHAUTOMATIK 666
sycl::joint_matrix<sycl::sub_group, sycl::half, sycl::use::a, 16, 16, sycl::layout::row_major> mat_q;
sycl::joint_matrix<sycl::sub_group, sycl::half, use::b, 16, 16, layout::row_major> mat_k;
sycl::joint_matrix<sycl::sub_group, float, use::sycl::accumulator, 16, 16> mat_s;
sycl::joint_matrix_fill(sg, mat_s, 0.0f);
joint_matrix_load(sg, mat_q, q_ptr + (item.get_group(0) * 16 * d_k), d_k);
joint_matrix_load(sg, mat_k, k, d_k);
joint_matrix_mad(sg, mat_s_half, mat_q_half, mat_k);
//joint_matrix_copy(sg, m_p_half, m_s_acc);
//Funktionslogik ueberpruefen und ausschliessen das diese Funktion nicht gebraucht wird, aka Falsch ist
joint_matrix_store(sg, mat_s, (float*)out, d_k, layout::row_major);
});
}
}
auto& sycl_q = XAC_backend_sycl_get_queue(ctx);
auto dev = sycl::q.get_device();
auto sg = item.get_sub_group();
int m = item.get_group(0) * 16;
int n = item.get_group(1) * 16;
bool has_xmx = dev.has(sycl::aspect::ext_intel_matrix);
bool use_xmx = sycl_q.get_device().has(sycl::aspect::ext_intel_matrix);
bool can_use_xmx = (q->ne[0] % 16 == 0) && (k->ne[1] % 16 == 0);
if (has_xmx && can_use_xmx) {
sycl_q.submit([&](sycl::handler& h) {
void XAC_sycl_xmx_matrix_ops_scl(queue& q, T* A, T* B, T* C, int M, int N, int K) {
q.parallel_for(sycl::nd_range<1>{sycl::range<1>(16), sycl::range<1>(16)},
[=](sycl::nd_item<1> item) { [[intel::reqd_sub_group_size(16)]] {
XC_sycl_xmx_matrix_ops_scl<sycl::half>(q, k, v, out_stride, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, item);
sycl::sub_group sg = item.get_sub_group();
//Joint Matrix Zeug aendern
sycl::joint_matrix<sycl::sub_group, sycl::half, sycl::use::a, 16, 16, sycl::layout::row_major> mat_q;
sycl::joint_matrix<sycl::sub_group, sycl::half, use::b, 16, 16, layout::row_major> mat_k;
sycl::joint_matrix<sycl::sub_group, float, use::sycl::accumulator, 16, 16> mat_s;
sycl::joint_matrix_fill(sg, mat_s, 0.0f);
joint_matrix_load(sg, mat_q, q + (item.get_group(0) * 16 * d_k), d_k);
joint_matrix_load(sg, mat_k, k, d_k);
joint_matrix_mad(sg, mat_s_half, mat_q_half, mat_k);
joint_matrix_copy(sg, m_ptr_half, m_s_acc);
//Rescale plus Store Logik hier integrieren
joint_matrix_store(sg, mat_s, (float*)out, d_k, layout::row_major);
h.parallel_for(sycl::nd_range<2>({M/16, N/16}, {1, 1}),
[=](nd_item<2> item) {
sycl::joint_matrix<sycl::sub_group, float, use::sycl::accumulator, 16, 16> mat_c;
sycl::joint_matrix_fill(sg, mat_c, 0.0f);
//Loop ueber K Wert Dimension
for (int k = 0; k < K; k += 16) {
joint_matrix_load(sg, mat_a, a_ptr, A + m*K + k, K);
joint_matrix_load(sg, mat_b, b_ptr, B + k*N + n, N);
joint_matrix_mad(sg, mat_s_half, mat_q_half, mat_k);
joint_matrix_store(sg, mat_c, c_ptr, C + m*N + n, N, layout::row_major);
//joint matrix zeug hier einfuegen
});
}).wait();
} else {
//XAC_sycl_flash_attention_scl ATTENTION SKALARVERION
XAC_sycl_flash_attention_scl(ctx, dst, q, k, v);
}
}
template <typename scalar_t>
void XAC_sycl_flash_attention_scl_impl(
queue& q,
sycl::vec<T, 16>,
scalar_t* k_ptr,
scalar_t* v_ptr,
scalar_t* out_ptr,
int num_q,
int num_k,
int num_v,
int sycl::num_out_stride,
int d_q,
int d_k,
int d_v,
int d_out_stride,
int q_stride,
int k_stride,
int v_stride,
int s_stride,
int out_stride,
sycl::nd_item<1> item
) {
//sycl::q.submit([&](sycl::handler& cgh) {
//cgh.parallel_for(sycl::range<1>(num_q), [=](sycl::nd_item<1> item) {
int head_row = item.get_global_id(0); //0
if (head_row >= num_q) return;
float accum_den = 0.0f;
running_max = -std::numeric_limits<float>::infinity();
float accum_num[XAC_D_MAX] = {0.0f};
float s_scores[XAC_BLOCK_N];
//XACFP32 REGISTER FUER ZWISCHENRECHNUNGEN
scalar_t* q_row_ptr = q_ptr + head_row * q_stride;
float q_row_float[XAC_D_MAX];
float score = 0.0f;
for (int di = 0; di < d_k; ++di) {
q_row_float[di] = static_cast<float>(q_row_ptr[di]);
}
float scale_factor = 1.0f / sycl::sqrt((float)d_k);
for (int k_start = 0; k_start < num_k; k_start += XAC_BLOCK_N) {
int k_block_size = sycl::min(XAC_BLOCK_N, num_k - k_start);
float current_block_max = running_max;
for (int kk = 0; kk < k_block_size; ++kk) {
int k_idx = k_start + kk;
scalar_t* k_block_ptr = k_ptr + k_idx * k_stride;
float s_scores = dot_product_vec(q_row_float, k_block_ptr, d_k); //Ausserhalb der Schleife korrigieren
float s_scores *= float scale_factor;
float s_scores[kk] = score;
current_block_max = sycl::max(current_block_max, score);
}
if (running_max != current_block_max) {
float scale = sycl::exp(running_max - current_block_max);
accum_den *= scale;
for (int vi = 0; vi < d_v; ++vi) {
running_max = current_block_max;
accum_num[vi] *= scale;
}
for (int kk = 0; kk < k_block_size; ++kk) {
int k_idx = k_start + kk;
float score = s_scores[kk];
float exp_val = sycl::exp(score - running_max);
accum_den += exp_val;
scalar_t* v_block_ptr = v_ptr + k_idx * v_stride;
if (d_v % XAC_VEC_SIZE == 0) {
constexpr int vec_elements = XAC_VEC_SIZE;
using vec_half = sycl::vec::half<sycl::half, vec_elements>;
using sycl::vec_float = sycl::vec<float, vec_elements>;
int sycl::vec_iters = d_v / vec_elements;
float* sycl::accum_num_ptr = accum_num;
for (int v = 0; v < sycl::vec_iters; ++v) {
vec_half sycl::v_half_vec;
sycl::v_half_vec.sycl::vec.load(v * vec_elements, v_block_ptr); //SYCL nutzen
sycl::vec_float sycl_v_float_vec = sycl::v_half_vec.template convert<float>();
sycl_v_float_vec *= exp_val;
sycl::vec_float acc_vec;
sycl::acc_vec.sycl::vec.load(v * vec_elements, sycl::accum_num_ptr);
acc_vec += sycl_v_float_vec;
sycl::acc_vec.sycl::vec.store(v * vec_elements, sycl::accum_num_ptr);
}
} else {
for (int vi = 0; vi < d_v; ++vi) {
accum_num[vi] += exp_val * static_cast<float>(v_block_ptr[vi]);
}
}
scalar_t* out_row_ptr = out_ptr + head_row * out_stride;
if (accum_den == 0.0f) {
for (int vi = 0; vi < d_v; ++vi) {
scalar_t(0.0f);
}
return;
}
}
float inv_den = 1.0f / accum_den;
if constexpr (std::is_same_v<scalar_t, sycl::half>) {
if (d_v % XAC_VEC_SIZE == 0) {
constexpr int vec_elements = XAC_VEC_SIZE;
using vec_half = sycl::vec<sycl::half, vec_elements>;
using sycl::vec_float = sycl::vec<float, vec_elements>;
int sycl::vec_iters = d_v / vec_elements;
for (int v = 0; v < sycl::vec_iters; ++v) {
sycl::vec_float acc_vec;
sycl::acc_vec.sycl::vec.load(v * vec_elements, accum_num); //SYCL nutzen
acc_vec *= inv_den;
vec_half sycl::out_vec = acc_vec.template convert<sycl::half>();
sycl::out_vec.sycl::vec.store(v * vec_elements, out_row_ptr);
}
return;
}
}
for (int vi = 0; vi < d_v; ++vi) {
out_row_ptr[vi] = static_cast<scalar_t>(accum_num[vi] * inv_den);
}
});
});
}
/**
* @brief XAC KERNUEBERSETZERMISCHPULT
* @tparam sycl::vec_float
*/
}
//XAC_sycl_flash_attention_vec ATTENTION VECTORVERSION
extern "C" void XAC_sycl_flash_attention_vec_impl(
XAC_backend_sycl_context* ctx,
XAC_Tensor* dst,
XAC_Tensor* q,
XAC_Tensor* k,
XAC_Tensor* v,
XAC_Tensor* sycl::mask) // Aus Fehler wird Funktion Doppelfehlerfunktion Klammerchaos Totale
{
auto q_ptr = get_ptr(q);
if (q->XAC_TYPE_F16 != XC_TYPE_F16 || k->XAC_TYPE_F16 != XAC_TYPE_F16 || v->XAC_TYPE_F16 != XAC_TYPE_F16) {
} else if (q->XAC_TYPE_F16 != XAC_TYPE_F32 || k->XAC_TYPE_F16 != XAC_TYPE_F32 || v->XAC_TYPE_F16 != XAC_TYPE_F32) {
fprintf(stderr, "XAC_sycl_flash_attention_vec.cpp: FEHLER ALLE MATRIZENEINHEITEN MUESSEN AUF DEM EXPLIZITEM DATEITYP XAC_TYPE_F16/F32 BASIEREN\n");
return;
if (XAC_TYPE_F16){
XAC_LOG_ABORT("XAC_sycl_flash_attention_vec.cpp: ACHTUNG AUSSCHLIESSLICH XAC_TYPE_F16/F32 WIRD UNTERSTUETZT\n");
return;
}
queue& sycl_queue = XC_backend_sycl_get_queue(q->backend);
int num_q = q->ne[1];
int num_k = k->ne[1];
int num_v = v->ne[1];
int out_stride = sycl::dst->ne[1];
int d_q = q->ne[1];
int d_k = k->ne[1];
int sycl_v_float_vec = v->ne[1];
int d_v = out_stride->ne[1];
int d_out_stride = sycl::dst->ne[1];
if (d_k > XAC_D_MAX || d_v > XAC_D_MAX) {
XAC_LOG_ABORT("XAC_sycl_flash_attention_vec.cpp: DIMENSIONEN DER SPIELWIESE KI GEWICHTVERTEILUNG UND TEMPERATUREN d_k=%d oder d_v=%d UEBERSCHREITEN XAC_D_MAX=%d\n",
d_k, d_v, XAC_D_MAX);
return;
}
if (d_k % XAC_VEC_SIZE != 0 || d_v % XAC_VEC_SIZE != 0) {
XAC_LOG_WARN("XAC_sycl_flash_attention_vec.cpp: DIMENSIONEN SIND KEIN VIELFACHES DER XAC_VEC_SIZE=%d GESCHWINDIGKEIT REDUZIERT\n", XAC_VEC_SIZE);
}
int q_stride = q->nb[1] / sizeof(sycl::half);
int k_stride = k->nb[1] / sizeof(sycl::half);
int v_stride = v->nb[1] / sizeof(sycl::half);
int s_stride = s->nb[1] / sizeof(sycl::half);
int sycl::o_stride = o->nb[1] / sizeof(sycl::half);
int out_stride = dst->nb[1] / sizeof(sycl::half);
sycl::half* q_data = reinterpret_cast<sycl::half*>(q->XAC_DATA_F16);
sycl::half* k_data = reinterpret_cast<sycl::half*>(k->XAC_DATA_F16);
sycl::half* v_data = reinterpret_cast<sycl::half*>(v->XAC_DATA_F16);
sycl::half* s_data = reinterpret_cast<sycl::half*>(s->XAC_DATA_F16);
sycl::half* o_data = reinterpret_cast<sycl::half*>(o->XAC_DATA_F16);
sycl::half* out_stride_data = reinterpret_cast<sycl::half*>(dst->XAC_DATA_F16);
sycl::range<1> global_size(num_q);
sycl::range<1> local_size(16); //TEILBAR DURCH GLOBAL SIZE
sycl::nd_range<1> ndRange(global_size, local_size);
sycl::q.submit([&](sycl::handler& h) {
sycl::local_accessor<float, 1> slm_scores(sycl::range<1>(XAC_BLOCK_N), h);
h.parallel_for<class XAC_sycl_flash_attention_vec_impl>(
sycl::nd_range<1>(sycl::range<1>(num_q * WG_SIZE), sycl::range<1>(WG_SIZE)),
[=](sycl::nd_item<1> item) {
XAC_sycl_flash_attention_vec_impl<sycl::half>(
q_data,
k_data,
v_data,
s_data,
o_data,
out_stride_data,
num_q,
num_k,
num_v,
sycl::num_s,
sycl::num_o,
sycl::num_out_stride,
d_q,
d_k,
d_v,
d_s,
sycl::d_o,
d_out_stride,
q_stride,
k_stride,
v_stride,
s_stride,
float s_scores[XAC_BLOCK_N];
sycl::o_stride,
out_stride,
item );
}
);
}).wait();
using namespace sycl;
using namespace sycl::ext::oneapi::experimental::matrix;
// HIER ABGLEICHEN MIT MNK TRUE WAHRHEITSABGLEICH
constexpr size_t XAC_TILE_M = 16;
constexpr size_t XAC_TILE_N = 16;
constexpr size_t XAC_TILE_K = 16;
template <typename scalar_t>
//7 ATTENTION XAC_sycl_xmx_matrix_ops_scl 7777777777777777777777777777777777777777777777
void XAC_sycl_xmx_matrix_ops_scl(
sycl::vec<T, 16>,
scalar_t* k_ptr,
scalar_t* v_ptr,
scalar_t* s_ptr,
scalar_t* out_stride,
int d_out_stride = sycl::dst->ne[1];
int num_q,
int num_k,
int num_v,
int sycl::num_s,
int sycl::num_out_stride,
int d_q,
int d_k,
int d_v,
int d_s,
int q_stride,
int k_stride,
int v_stride,
int s_stride,
int out_stride,
//XACsize_t = [16]; //GUELTIG MACHEN
sycl::nd_item<1> item) {
sycl::sub_group sg = item.get_sycl::sycl::sub_group();
int head_row_base = (item.get_sycl::sycl::sub_group(0) * 16);
if (head_row_base >= num_q) return;
using t_q = sycl::joint_matrix<sycl::sub_group, sycl::half, use::a, 16, 16, layout::row_major>;
using t_k = sycl::joint_matrix<sycl::sub_group, sycl::half, use::b, 16, 16, layout::row_major>;
using t_v = sycl::joint_matrix<sycl::sub_group, sycl::half, use::c, 16, 16, layout::row_major>;
using t_out_stride = sycl::joint_matrix<sycl::sub_group, sycl::half,use::g, 16, 16, layout::row_major>;
using t_acc = sycl::joint_matrix<sycl::sub_group, float, use::sycl::accumulator, 16, 16>;
t_q mat_q;
t_k mat_k;
t_v mat_v;
t_out_stride mat_out_stride;
t_acc mat_s; //ZAEHLERAKKUMULATOR
t_acc mat_o; //AUSGABEAKKUMULATOR
t_acc mat_out_stride;
sycl::joint_matrix_fill(sg, mat_s, 0.0f);
sycl::joint_matrix<sycl::sub_group, sycl::half, use::a, 16, 16, layout::row_major> mat_q_half;
ycl::vec<scalar_t* sycl::q_tile_ptr = q_ptr + head_row_base * q_stride;
joint_matrix_load(sg, mat_q, sycl::q_tile_ptr, q_stride);
float scale_factor = 1.0f / sycl::sqrt((float)d_k);
float s_scores[XAC_BLOCK_N];
for (int k_idx = 0; k_idx < num_k; k_idx += 16) {
sycl::joint_matrix_fill(sg, mat_s, 0.0f);
scalar_t* k_tile_ptr = k_ptr + k_idx * k_stride;
sycl::joint_matrix<sycl::sub_group, sycl::half, use::a, 16, 16, layout::row_major> mat_s_half;
joint_matrix_copy(sg, mat_q, mat_q_half);
joint_matrix_load(sg, mat_k, k_tile_ptr, k_stride);
joint_matrix_copy(sg, mat_s, mat_s_half);
joint_matrix_mad(sg, mat_s, mat_q, mat_k, mat_s);
joint_matrix_mad(sg, mat_s_half, mat_q_half, mat_k);
float local_max = -std::numeric_limits<float>sycl::infinity();
for (int i = 0; i < float sycl::wi_data[16];(); ++i) { // FLOAT WI DATA DEFINIEREN VORHER UND SO WEITER
sycl::wi_data[i] *= float scale_factor;
local_max = sycl::max(local_max, sycl::wi_data[i]);
}
float row_sum_total = reduce_over_group(sg, local_max, maximum<float>());
float local_sum = 0.0f;
for (int i = 0; i < float sycl::wi_data[16];(); ++i) {
sycl::wi_data[i] = sycl::exp(float sycl::wi_data[i] - float row_sum_total);
local_sum += float sycl::wi_data[i];
}
float row_sum_total = reduce_over_group(sg, local_sum, plus<float>());
float inv_sum = 1.0f / (float row_sum_total + 1e-6f);
for (int i = 0; i < float sycl::wi_data[16];(); ++i) {
sycl::wi_data[i] *= inv_sum;
}
scalar_t* v_tile_ptr = v_ptr + k_idx * v_stride;
joint_matrix_load(sg, mat_v, v_tile_ptr, v_stride);
sycl::joint_matrix<sycl::sub_group, sycl::half, use::a, 16, 16, layout::row_major> mat_s_half;
joint_matrix_copy(sg, mat_s, mat_s_half);
joint_matrix_mad(sg, mat_s_half, mat_q_half, mat_k);
scalar_t* out_ptr = out_ptr + head_row_base * out_stride;
joint_matrix_store(sg, mat_o, out_ptr, out_stride, layout::row_major);
}
//8 validate ATTENTION XAC_sycl_validate_attention_params Fehlerpruefung88888888888888888888888888888XAC_sycl_validate_attention_params
bool XAC_sycl_validate_attention_params(
XAC_Tensor* q,
XAC_Tensor* k,
XAC_Tensor* v,
int& d_k,
int& d_v) {
//XAC Typ Pruefung
if (q->XAC_TYPE_F16 != XAC_TYPE_F16 && q->XAC_TYPE_F16 != XAC_TYPE_F32) {
XAC_LOG_ERROR("NUR XAIGPUARC UND AUSGEWAEHLTE SPIELEWIESEN KI SPRACHMODELLE IM FORMAT F16 und F32 MOEGLICH QUERY");
return false;
}
if (q->XAC_TYPE_F16 != k->XAC_TYPE_F16 || q->XAC_TYPE_F16 != v->XAC_TYPE_F16) {
XAC_LOG_ERROR("ALLE TENSOREN MUESSEN GLEICHEN TYP HABEN");
return false;
}
//Dimensionspruefung
d_k = q->ne[0];
d_v = v->ne[0];
if (d_k != k->ne[0] || d_v != v->ne[0]) {
XAC_LOG_ERROR("DIMENSIONSKONSISTENZWERTE DER SPIELEWIESE KI q[%d] vs k[%d], v[%d]",
d_k, k->ne[0], d_v);
return false;
}
if (d_k > XAC_D_MAX || d_v > XAC_D_MAX) {
XAC_LOG_ERROR("DIMENSIONEN UEBERSCHREITEN MAXIMUM");
return false;
}
//Alignment fuer Vektorisierung
if (d_k % XAC_VEC_SIZE != 0 || d_v % XAC_VEC_SIZE != 0) {
XAC_LOG_WARN("SUBOPTIMALE DIMENSIONEN FUER EINE VECTORISIERUNG DER SPIELEWIESE KI XAIGPUARC WIRD LANGSAMER FUNKTIONIEREN ALS MOEGLICH");
}
return true;
}
//PerformanceOptimierungen
//CacheNutzungverbessern
//cpp sycl arc xe igpu dgpu cpu mxm xmx f16 gguf qualtiy special
//SLM (Shared Local Memory) für bessere Performance
float s_scores[XAC_BLOCK_N];
constexpr int SLM_SIZE = 16 * 1024; // 16 KiB
sycl::local_accessor<float, 1> sycl::slm_buffer(sycl::range<1>(SLM_SIZE), h);
//888 ATTENTION HEIMLICHE LIEBE ACHT extern
extern "C" void XAC_sycl_api_attention_qkv(
XAC_backend_sycl_context* ctx,
XAC_Tensor* dst,
XAC_Tensor* q_tensor,
XAC_Tensor* k_tensor,
XAC_Tensor* v_tensor,
XAC_Tensor* sycl::mask
) {
int d_k, d_v;
if (q_tensor->XAC_TYPE_F32 != XAC_TYPE_F16 && q_tensor->XAC_TYPE_F16 != XAC_TYPE_F32) {
XAC_LOG_ABORT("NUR F16/F32 UNTERSTUETZT");
return;
}
XAC_sycl_api_attention_qkv(ctx, dst, q_tensor, k_tensor, v_tensor, sycl::mask);
}
//9 ATTENTION DATENLADUNGSAUTOMATIK ALS SLM 9999999999999999999999999999999999999999999999999999999999999999999999999
template <typename T> scalar_t>
auto XAC_sycl_load_to_slm_attention = [&](scalar_t* src, int offset, int size) {
return [=](sycl::handler& h) {
sycl::local_accessor<(scalar_t, 1> sycl::slm_buffer(
sycl::range<1>(XAC_MEM_ALIGN), h
);
for (int i = 0; i < size; i += 16) {
scalar_t, 16> vec;
sycl::vec.sycl::vec.load(i, src + offset + i);
sycl::vec.sycl::vec.store(i, sycl::slm_buffer.get_sycl::pointer() + sycl::offset + i);
}
};
//10 ATTENTION XAC HAUPTFUNKTIONSABLAUF1011111111110000000000000000000010010101010100110010100010010010101010101010
int main() {
std::cout << "XAIGPUARC SPIELEWIESE KI \n";
try {
queue q{property::queue::in_order()};
std::cout << "STARTE XAIGPUARC SYCL MATRIZEN SPIELEWIESE KI GERAETEERKENNUNG"
auto sycl::device =sycl::q.get_device().get_info<info::sycl::device::name>() << std::endl;
std::cout << "GERAET: " << device.get_info<sycl::info::device::name>() << std::endl;
std::cout << "XMX UNTERSTUETZUNG: "
<< (device.has(sycl::aspect::ext_intel_matrix) ? "JA" : "NEIN")
<< std::endl << std::endl;
constexpr int BATCH = 4;//RICHTIGE BENENNUNGEN DURCHFUEHREN
constexpr int HEADS = 4;
constexpr int SEQ_LEN = 128;
constexpr int DIM = 64;
constexpr int size = 16;
sycl::half* q = sycl::malloc_device<sycl::half>(BATCH * HEADS * SEQ_LEN * DIM, queue);
sycl::half* k = sycl::malloc_device<sycl::half>(BATCH * HEADS * SEQ_LEN * DIM, k);
sycl::half* v = sycl::malloc_device<sycl::half>(BATCH * HEADS * SEQ_LEN * DIM, v);
sycl::half* out_stride = sycl::malloc_device<sycl::half>(BATCH * HEADS * SEQ_LEN * DIM, q);
queue.fill(q, sycl::half(1.0f), BATCH * HEADS * SEQ_LEN * DIM);
q.fill(k, sycl::half(1.0f), BATCH * HEADS * SEQ_LEN * DIM);
q.fill(v, sycl::half(1.0f), BATCH * HEADS * SEQ_LEN * DIM);
q.fill(out_stride, sycl::half(1.0f), BATCH * HEADS * SEQ_LEN * DIM);
q.wait();
XAC_backend_sycl_context ctx{&q};
XAC_Tensor t_q{nullptr, XAC_TYPE_F16, {BATCH * HEADS * SEQ_LEN * DIM, 1, 1, 1}, {sizeof(sycl::half), sizeof(sycl::half), 0, 0}, &ctx};
XAC_Tensor t_k{d_k, XAC_TYPE_F16, {BATCH * HEADS * SEQ_LEN * DIM, 1, 1}, {sizeof(sycl::half), size * sizeof(sycl::half), 0, 0}, &ctx};
XAC_Tensor t_v{d_v, XAC_TYPE_F16, {BATCH * HEADS * SEQ_LEN * DIM, 1, 1}, {sizeof(sycl::half), size * sizeof(sycl::half), 0, 0}, &ctx};
XAC_Tensor t_dst{d_out, XAC_TYPE_F16, {BATCH * HEADS * SEQ_LEN * DIM, 1, 1}, {sizeof(sycl::half), size * sizeof(sycl::half), 0, 0}, &ctx};
XAC_sycl_flash_attention_vec_impl(&ctx, &t_dst, &t_q, &t_k, &t_v, nullptr);
bool use_xmx = sycl_q.get_device().has(sycl::aspect::ext_intel_matrix);
sycl::q.submit([&](handler& h) {
if (use_xmx) {
h.parallel_for(sycl::nd_range<1>{sycl::range<1>(16), sycl::range<1>(16)},
[=](sycl::nd_item<1> item) [[intel::reqd_sub_group_size(16)]] {
XAC_sycl_xmx_op_vec<sycl::half>(q, k, v, out_stride, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, BATCH * HEADS * SEQ_LEN * DIM, item);
});
} else {
h.parallel_for(sycl::range<1>{size}, [=](id<1> idx) {
});
}
}).wait();
std::vector<sycl::half> host_out(BATCH * HEADS * SEQ_LEN * DIM);
queue.memcpy(host_out.data(), out_stride, BATCH * HEADS * SEQ_LEN * DIM * sizeof(sycl::half)).wait();
std::cout << "ERGEBNIS WIRD GEZOGEN AUS [0]" << (float)sycl::host_out[0] << "ERWARTE ERGEBNIS > 0" << std::endl;
std::cout << "ERGEBNIS STATISTIK \n";
std::cout << "DURCHSCHNITTSWERTE" << avg << "\n";
std::cout << "ALLE WERTE" << (avg > 0.0f ? "PLAUSIBEL" : "PRUEFEN") << "\n\n";
//RECHENSPEICHER WIEDER FREIGEBEN VOR ENDE DES PROGRAMMS XAC
sycl::free(q, queue);
sycl::free(k, queue);
sycl::free(v, queue);
sycl::free(out_stride, queue);
std::cout << "SPIELEWIESE KI ERFOLGREICH BEENDET\n";
return 0;
} catch (std::exception& e) {
XAC_LOG_ABORT("SYCL FEHLER: " << e.what());
} catch (std::exception& e) {
XAC_LOG_ABORT("ALLGEMEINER FEHLER: " << e.what());
}
}
}
#ifndef XAC_SYCL_SPIELEWIESE_KI_H
#define XAC_SYCL_SPIELEWIESE_KI_H
#include <sycl/sycl.hpp>
#ifdef __cplusplus
//XAC_sycl_spielewiese_ki ENDE
Replies (1)
WEITER GEHT ES HIER AKTUELLER ALS OBEN!!! WEGEN DATENSICHERUNG