@@ -1,6 +1,5 @@
import Foundation
import Foundation
import Metal
import Metal
import MetalPerformanceShaders
import Accelerate
import Accelerate
// / E m b e d d i n g G e m m a c o n f i g u r a t i o n
// / E m b e d d i n g G e m m a c o n f i g u r a t i o n
@@ -42,6 +41,7 @@ public struct EmbeddingGemmaConfig: Codable {
}
}
}
}
// / E m b e d d i n g G e m m a - G o o g l e ' s 3 0 0 M p a r a m e t e r e m b e d d i n g m o d e l
public final class EmbeddingGemmaModel : @ unchecked Sendable {
public final class EmbeddingGemmaModel : @ unchecked Sendable {
public let config : EmbeddingGemmaConfig
public let config : EmbeddingGemmaConfig
public let engine : MarkBaseEngine
public let engine : MarkBaseEngine
@@ -67,12 +67,12 @@ public final class EmbeddingGemmaModel: @unchecked Sendable {
self . tokenizer = try TokenizerFactory . load ( modelDir : modelDir )
self . tokenizer = try TokenizerFactory . load ( modelDir : modelDir )
self . reader = try SafeTensorsReader ( path : modelDir + " /model.safetensors " )
self . reader = try SafeTensorsReader ( path : modelDir + " /model.safetensors " )
try loadWeights ( )
try loadWeights ( )
print ( " ✓ EmbeddingGemma loaded ( \( config . numHiddenLayers ) layers, hidden= \( config . hiddenSize ) ) " )
}
}
private func loadWeights ( ) throws {
private func loadWeights ( ) throws {
let embedData = try readTensor ( " embed_tokens.weight " )
let embedData = try readTensor ( " embed_tokens.weight " )
embedTokens = engine . device . makeBuffer ( bytes : embedData , length : embedData . count * 4 ) !
embedTokens = engine . device . makeBuffer ( bytes : embedData , length : embedData . count * 4 ) !
for i in 0. . < config . numHiddenLayers {
for i in 0. . < config . numHiddenLayers {
let p = " layers. \( i ) "
let p = " layers. \( i ) "
layerNorms . append ( [
layerNorms . append ( [
@@ -91,44 +91,39 @@ public final class EmbeddingGemmaModel: @unchecked Sendable {
upProjs . append ( try loadAndTranspose ( " \( p ) .mlp.up_proj.weight " , rows : config . intermediateSize , cols : config . hiddenSize ) )
upProjs . append ( try loadAndTranspose ( " \( p ) .mlp.up_proj.weight " , rows : config . intermediateSize , cols : config . hiddenSize ) )
downProjs . append ( try loadAndTranspose ( " \( p ) .mlp.down_proj.weight " , rows : config . hiddenSize , cols : config . intermediateSize ) )
downProjs . append ( try loadAndTranspose ( " \( p ) .mlp.down_proj.weight " , rows : config . hiddenSize , cols : config . intermediateSize ) )
}
}
let fnData = try readTensor ( " norm.weight " )
let fnData = try readTensor ( " norm.weight " )
finalNorm = engine . device . makeBuffer ( bytes : fnData , length : fnData . count * 4 ) !
finalNorm = engine . device . makeBuffer ( bytes : fnData , length : fnData . count * 4 ) !
}
}
private func loadAndTranspose ( _ name : String , rows : Int , cols : Int ) throws -> MTLBuffer {
let data = try readTensor ( name )
var transposed = [ Float ] ( repeating : 0 , count : data . count )
for r in 0. . < rows {
for c in 0. . < cols {
transposed [ c * rows + r ] = data [ r * cols + c ]
}
}
return engine . device . makeBuffer ( bytes : transposed , length : transposed . count * 4 ) !
}
public func embed ( text : String , maxLen : Int = 2048 ) throws -> [ Float ] {
public func embed ( text : String , maxLen : Int = 2048 ) throws -> [ Float ] {
var tokens = tokenizer . encode ( text : text )
var tokens = tokenizer . encode ( text : text )
if tokens . count > maxLen { tokens = Array ( tokens . prefix ( maxLen ) ) }
if tokens . count > maxLen { tokens = Array ( tokens . prefix ( maxLen ) ) }
guard ! tokens . isEmpty else { return [ ] }
guard ! tokens . isEmpty else { return [ ] }
let seqLen = tokens . count , hs = config . hiddenSize
let seqLen = tokens . count , hs = config . hiddenSize
// T e s t 1 : E m b e d d i n g l o o k u p o n l y
print ( " TEST: Embedding lookup... " )
let cmdBuf1 = engine . commandQueue . makeCommandBuffer ( ) !
let inputBuf = try lookupEmbeddings ( tokens : tokens , cmdBuf : cmdBuf1 )
cmdBuf1 . commit ( )
cmdBuf1 . waitUntilCompleted ( )
print ( " TEST: Embedding lookup OK " )
// T e s t 2 : S i n g l e l a y e r f o r w a r d ( l a y e r 0 o n l y )
print ( " TEST: Layer 0 forward... " )
let cmdBuf2 = engine . commandQueue . makeCommandBuffer ( ) !
var hidden = try forwardLayerDebug ( hidden : inputBuf , layerIdx : 0 , seqLen : seqLen , cmdBuf : cmdBuf2 )
cmdBuf2 . commit ( )
cmdBuf2 . waitUntilCompleted ( )
print ( " TEST: Layer 0 OK " )
// F u l l f o r w a r d p a s s
print ( " TEST: Full forward pass... " )
let cmdBuf = engine . commandQueue . makeCommandBuffer ( ) !
let cmdBuf = engine . commandQueue . makeCommandBuffer ( ) !
hidden = inputBuf
let inputBuf = try lookupEmbeddings ( tokens : tokens , cmdBuf : cmdBuf )
var hidden = inputBuf
for idx in 0. . < config . numHiddenLayers {
for idx in 0. . < config . numHiddenLayers {
if idx % 6 = = 0 { print ( " Layer \( idx ) / \( config . numHiddenLayers ) " ) }
hidden = try forwardLayer ( hidden : hidden , layerIdx : idx , seqLen : seqLen , cmdBuf : cmdBuf )
hidden = try forwardLayerDebug ( hidden : hidden , layerIdx : idx , seqLen : seqLen , cmdBuf : cmdBuf )
}
}
print ( " TEST: All layers OK " )
let output = try applyRmsNorm ( input : hidden , weight : finalNorm , count : seqLen * hs , cmdBuf : cmdBuf )
let output = try applyRmsNorm ( input : hidden , weight : finalNorm , count : seqLen * hs , cmdBuf : cmdBuf )
cmdBuf . commit ( )
cmdBuf . commit ( )
cmdBuf . waitUntilCompleted ( )
cmdBuf . waitUntilCompleted ( )
@@ -140,10 +135,12 @@ public final class EmbeddingGemmaModel: @unchecked Sendable {
}
}
let n = Float ( seqLen )
let n = Float ( seqLen )
for i in 0. . < hs { embedding [ i ] /= n }
for i in 0. . < hs { embedding [ i ] /= n }
var norm : Float = 0
var norm : Float = 0
for i in 0. . < hs { norm += embedding [ i ] * embedding [ i ] }
for i in 0. . < hs { norm += embedding [ i ] * embedding [ i ] }
norm = sqrt ( norm )
norm = sqrt ( norm )
if norm > 0 { for i in 0. . < hs { embedding [ i ] /= norm } }
if norm > 0 { for i in 0. . < hs { embedding [ i ] /= norm } }
return embedding
return embedding
}
}
@@ -162,39 +159,19 @@ public final class EmbeddingGemmaModel: @unchecked Sendable {
return engine . device . makeBuffer ( bytes : data , length : data . count * 4 ) !
return engine . device . makeBuffer ( bytes : data , length : data . count * 4 ) !
}
}
private func loadAndTranspose ( _ name : String , rows : Int , cols : Int ) throws -> MTLBuffer {
// L o a d [ r o w s , c o l s ] a n d t r a n s p o s e t o [ c o l s , r o w s ] f o r M P S m a t m u l C = A × B
let data = try readTensor ( name )
var transposed = [ Float ] ( repeating : 0 , count : data . count )
for r in 0. . < rows {
for c in 0. . < cols {
transposed [ c * rows + r ] = data [ r * cols + c ]
}
}
return engine . device . makeBuffer ( bytes : transposed , length : transposed . count * 4 ) !
}
private func lookupEmbeddings ( tokens : [ Int ] , cmdBuf : MTLCommandBuffer ) throws -> MTLBuffer {
private func lookupEmbeddings ( tokens : [ Int ] , cmdBuf : MTLCommandBuffer ) throws -> MTLBuffer {
let seqLen = tokens . count , hs = config . hiddenSize
let seqLen = tokens . count , hs = config . hiddenSize
print ( " lookupEmbeddings: seqLen= \( seqLen ) , hs= \( hs ) " )
// C P U - b a s e d e m b e d d i n g l o o k u p
// R e a d e m b e d d i n g t a b l e t o C P U
let embedPtr = embedTokens . contents ( ) . assumingMemoryBound ( to : Float . self )
let embedPtr = embedTokens . contents ( ) . assumingMemoryBound ( to : Float . self )
let embedCount = embedTokens . length / 4
let embedArray = Array ( UnsafeBufferPointer ( start : embedPtr , count : embedCount ) )
print ( " Read \( embedCount ) floats from embedTokens " )
// L o o k u p e m b e d d i n g s f o r t o k e n s
var embedData = [ Float ] ( repeating : 0 , count : seqLen * hs )
var embedData = [ Float ] ( repeating : 0 , count : seqLen * hs )
for ( i , token ) in tokens . enumerated ( ) {
for ( i , token ) in tokens . enumerated ( ) {
let start = i * hs
let dstStart = i * hs
let srcStart = token * hs
let srcStart = token * hs
embedData [ start . . < start + hs ] = embedArray [ srcStart . . < srcStart + hs ]
for j in 0. . < hs {
embedData [ dstStart + j ] = embedPtr [ srcStart + j ]
}
}
print ( " Looked up \( seqLen ) tokens " )
}
return engine . device . makeBuffer ( bytes : embedData , length : embedData . count * 4 ) !
let buf = engine . device . makeBuffer ( bytes : embedData , length : embedData . count * 4 ) !
print ( " Created MTLBuffer " )
return buf
}
}
private func applyRmsNorm ( input : MTLBuffer , weight : MTLBuffer , count : Int , cmdBuf : MTLCommandBuffer ) throws -> MTLBuffer {
private func applyRmsNorm ( input : MTLBuffer , weight : MTLBuffer , count : Int , cmdBuf : MTLCommandBuffer ) throws -> MTLBuffer {
@@ -209,29 +186,26 @@ public final class EmbeddingGemmaModel: @unchecked Sendable {
var c = UInt32 ( count ) , e : Float = config . rmsNormEps
var c = UInt32 ( count ) , e : Float = config . rmsNormEps
enc . setBytes ( & c , length : 4 , index : 3 )
enc . setBytes ( & c , length : 4 , index : 3 )
enc . setBytes ( & e , length : 4 , index : 4 )
enc . setBytes ( & e , length : 4 , index : 4 )
enc . dispatchThreads ( MTLSize ( width : count , height : 1 , depth : 1 ) , threadsPerThreadgroup : MTLSize ( width : min ( 256 , count ) , height : 1 , depth : 1 ) )
enc . dispatchThreads ( MTLSize ( width : count , height : 1 , depth : 1 ) ,
threadsPerThreadgroup : MTLSize ( width : min ( 256 , count ) , height : 1 , depth : 1 ) )
return output
return output
}
}
private func matmulSeq ( input : MTLBuffer , weight : MTLBuffer , output : MTLBuffer , m : Int , k : Int , n : Int , cmdBuf : MTLCommandBuffer ) throws {
private func matmulSeq ( input : MTLBuffer , weight : MTLBuffer , output : MTLBuffer , m : Int , k : Int , n : Int , cmdBuf : MTLCommandBuffer ) throws {
// U s e M P S f o r o p t i m i z e d m a t r i x m u l t i p l i c a t i o n o n A p p l e S i l i c o n
let enc = cmdBuf . makeComputeCommandEncoder ( ) !
// W e i g h t i s s t o r e d t r a n s p o s e d [ k , n ] f o r C = A × B
let pso = try engine . pipeline ( named : " matmul_f32 " )
let descA = MPSMatrixDescriptor ( rows : m , columns : k , rowBytes : k * 4 , dataType : . float32 )
enc . setComputePipelineState ( pso )
let descB = MPSMatrixDescriptor ( rows : k , columns : n , rowBytes : n * 4 , dataType : . float32 )
enc . setBuffer ( input , offset : 0 , index : 0 )
let descC = MPSMatrixDescriptor ( rows : m , columns : n , rowBytes : n * 4 , dataType : . float32 )
enc . setBuffer ( weight , offset : 0 , index : 1 )
let matA = MPSMatrix ( buffer : input , descriptor : descA )
enc . setBuffer ( output , offset : 0 , index : 2 )
let matB = MPSMatrix ( buffer : weight , descriptor : descB )
var mm = UInt32 ( m ) , kk = UInt32 ( k ) , nn = UInt32 ( n )
let matC = MPSMatrix ( buffer : output , descriptor : descC )
enc . setBytes ( & mm , length : 4 , index : 3 )
enc . setBytes ( & kk , length : 4 , index : 4 )
let matMul = MPSMatrixMultiplication ( device : engine . device ,
enc . setBytes ( & nn , length : 4 , index : 5 )
transposeLeft : false ,
let total = m * n
transposeRight : false ,
enc . dispatchThreads ( MTLSize ( width : total , height : 1 , depth : 1 ) ,
resultRows : m ,
threadsPerThreadgroup : MTLSize ( width : min ( 256 , total ) , height : 1 , depth : 1 ) )
resultColumns : n ,
enc . endEncoding ( )
interiorColumns : k ,
alpha : 1.0 ,
beta : 0.0 )
matMul . encode ( commandBuffer : cmdBuf , leftMatrix : matA , rightMatrix : matB , resultMatrix : matC )
}
}
private func eltwiseAdd ( a : MTLBuffer , b : MTLBuffer , output : MTLBuffer , count : Int , cmdBuf : MTLCommandBuffer ) throws {
private func eltwiseAdd ( a : MTLBuffer , b : MTLBuffer , output : MTLBuffer , count : Int , cmdBuf : MTLCommandBuffer ) throws {
@@ -244,7 +218,8 @@ public final class EmbeddingGemmaModel: @unchecked Sendable {
enc . setBuffer ( output , offset : 0 , index : 2 )
enc . setBuffer ( output , offset : 0 , index : 2 )
var c = UInt32 ( count )
var c = UInt32 ( count )
enc . setBytes ( & c , length : 4 , index : 3 )
enc . setBytes ( & c , length : 4 , index : 3 )
enc . dispatchThreads ( MTLSize ( width : count , height : 1 , depth : 1 ) , threadsPerThreadgroup : MTLSize ( width : min ( 256 , count ) , height : 1 , depth : 1 ) )
enc . dispatchThreads ( MTLSize ( width : count , height : 1 , depth : 1 ) ,
threadsPerThreadgroup : MTLSize ( width : min ( 256 , count ) , height : 1 , depth : 1 ) )
}
}
private func geluMul ( gate : MTLBuffer , up : MTLBuffer , output : MTLBuffer , count : Int , cmdBuf : MTLCommandBuffer ) throws {
private func geluMul ( gate : MTLBuffer , up : MTLBuffer , output : MTLBuffer , count : Int , cmdBuf : MTLCommandBuffer ) throws {
@@ -257,7 +232,8 @@ public final class EmbeddingGemmaModel: @unchecked Sendable {
enc . setBuffer ( output , offset : 0 , index : 2 )
enc . setBuffer ( output , offset : 0 , index : 2 )
var c = UInt32 ( count )
var c = UInt32 ( count )
enc . setBytes ( & c , length : 4 , index : 3 )
enc . setBytes ( & c , length : 4 , index : 3 )
enc . dispatchThreads ( MTLSize ( width : count , height : 1 , depth : 1 ) , threadsPerThreadgroup : MTLSize ( width : min ( 256 , count ) , height : 1 , depth : 1 ) )
enc . dispatchThreads ( MTLSize ( width : count , height : 1 , depth : 1 ) ,
threadsPerThreadgroup : MTLSize ( width : min ( 256 , count ) , height : 1 , depth : 1 ) )
}
}
private func applyRoPE ( q : MTLBuffer , k : MTLBuffer , seqLen : Int , headDim : Int , numHeads : Int , cmdBuf : MTLCommandBuffer ) throws {
private func applyRoPE ( q : MTLBuffer , k : MTLBuffer , seqLen : Int , headDim : Int , numHeads : Int , cmdBuf : MTLCommandBuffer ) throws {
@@ -273,7 +249,8 @@ public final class EmbeddingGemmaModel: @unchecked Sendable {
enc . setBytes ( & hd , length : 4 , index : 3 )
enc . setBytes ( & hd , length : 4 , index : 3 )
enc . setBytes ( & nh , length : 4 , index : 4 )
enc . setBytes ( & nh , length : 4 , index : 4 )
enc . setBytes ( & rt , length : 4 , index : 5 )
enc . setBytes ( & rt , length : 4 , index : 5 )
enc . dispatchThreads ( MTLSize ( width : numHeads * headDim / 2 , height : 1 , depth : 1 ) , threadsPerThreadgroup : MTLSize ( width : min ( 256 , numHeads * headDim / 2 ) , height : 1 , depth : 1 ) )
enc . dispatchThreads ( MTLSize ( width : numHeads * headDim / 2 , height : 1 , depth : 1 ) ,
threadsPerThreadgroup : MTLSize ( width : min ( 256 , numHeads * headDim / 2 ) , height : 1 , depth : 1 ) )
}
}
private func bidirectionalAttention ( q : MTLBuffer , k : MTLBuffer , v : MTLBuffer , output : MTLBuffer , seqLen : Int , cmdBuf : MTLCommandBuffer ) throws {
private func bidirectionalAttention ( q : MTLBuffer , k : MTLBuffer , v : MTLBuffer , output : MTLBuffer , seqLen : Int , cmdBuf : MTLCommandBuffer ) throws {
@@ -296,81 +273,55 @@ public final class EmbeddingGemmaModel: @unchecked Sendable {
enc . setBytes ( & scale , length : 4 , index : 9 )
enc . setBytes ( & scale , length : 4 , index : 9 )
let tgMem = config . slidingWindow * 4
let tgMem = config . slidingWindow * 4
enc . setThreadgroupMemoryLength ( tgMem , index : 0 )
enc . setThreadgroupMemoryLength ( tgMem , index : 0 )
enc . dispatchThreads ( MTLSize ( width : seqLen * config . numAttentionHeads , height : 1 , depth : 1 ) , threadsPerThreadgroup : MTLSize ( width : min ( 256 , seqLen * config . numAttentionHeads ) , height : 1 , depth : 1 ) )
enc . dispatchThreads ( MTLSize ( width : seqLen * config . numAttentionHeads , height : 1 , depth : 1 ) ,
threadsPerThreadgroup : MTLSize ( width : min ( 256 , seqLen * config . numAttentionHeads ) , height : 1 , depth : 1 ) )
}
}
private func forwardLayerDebug ( hidden : MTLBuffer , layerIdx : Int , seqLen : Int , cmdBuf : MTLCommandBuffer ) throws -> MTLBuffer {
private func forwardLayer ( hidden : MTLBuffer , layerIdx : Int , seqLen : Int , cmdBuf : MTLCommandBuffer ) throws -> MTLBuffer {
let hs = config . hiddenSize , device = engine . device
let hs = config . hiddenSize , device = engine . device
let hDim = config . headDim , nH = config . numAttentionHeads , nKV = config . numKeyValueHeads
let hDim = config . headDim , nH = config . numAttentionHeads , nKV = config . numKeyValueHeads
let intermedi = config . intermediateSize
let intermedi = config . intermediateSize
print ( " Residual copy... " )
let resid = device . makeBuffer ( length : seqLen * hs * 4 ) !
let resid = device . makeBuffer ( length : seqLen * hs * 4 ) !
let blit = cmdBuf . makeBlitCommandEncoder ( ) !
let blit = cmdBuf . makeBlitCommandEncoder ( ) !
blit . copy ( from : hidden , sourceOffset : 0 , to : resid , destinationOffset : 0 , size : seqLen * hs * 4 )
blit . copy ( from : hidden , sourceOffset : 0 , to : resid , destinationOffset : 0 , size : seqLen * hs * 4 )
blit . endEncoding ( )
blit . endEncoding ( )
print ( " Input norm... " )
let h1 = try applyRmsNorm ( input : hidden , weight : layerNorms [ layerIdx ] [ 0 ] , count : seqLen * hs , cmdBuf : cmdBuf )
let h1 = try applyRmsNorm ( input : hidden , weight : layerNorms [ layerIdx ] [ 0 ] , count : seqLen * hs , cmdBuf : cmdBuf )
print ( " QKV projections... " )
let qBuf = device . makeBuffer ( length : seqLen * nH * hDim * 4 ) !
let qBuf = device . makeBuffer ( length : seqLen * nH * hDim * 4 ) !
let kBuf = device . makeBuffer ( length : seqLen * nKV * hDim * 4 ) !
let kBuf = device . makeBuffer ( length : seqLen * nKV * hDim * 4 ) !
let vBuf = device . makeBuffer ( length : seqLen * nKV * hDim * 4 ) !
let vBuf = device . makeBuffer ( length : seqLen * nKV * hDim * 4 ) !
try matmulSeq ( input : h1 , weight : qProjs [ layerIdx ] , output : qBuf , m : seqLen , k : hs , n : nH * hDim , cmdBuf : cmdBuf )
try matmulSeq ( input : h1 , weight : qProjs [ layerIdx ] , output : qBuf , m : seqLen , k : hs , n : nH * hDim , cmdBuf : cmdBuf )
print ( " Q done " )
try matmulSeq ( input : h1 , weight : kProjs [ layerIdx ] , output : kBuf , m : seqLen , k : hs , n : nKV * hDim , cmdBuf : cmdBuf )
try matmulSeq ( input : h1 , weight : kProjs [ layerIdx ] , output : kBuf , m : seqLen , k : hs , n : nKV * hDim , cmdBuf : cmdBuf )
print ( " K done " )
try matmulSeq ( input : h1 , weight : vProjs [ layerIdx ] , output : vBuf , m : seqLen , k : hs , n : nKV * hDim , cmdBuf : cmdBuf )
try matmulSeq ( input : h1 , weight : vProjs [ layerIdx ] , output : vBuf , m : seqLen , k : hs , n : nKV * hDim , cmdBuf : cmdBuf )
print ( " V done " )
print ( " RoPE... " )
try applyRoPE ( q : qBuf , k : kBuf , seqLen : seqLen , headDim : hDim , numHeads : nH , cmdBuf : cmdBuf )
try applyRoPE ( q : qBuf , k : kBuf , seqLen : seqLen , headDim : hDim , numHeads : nH , cmdBuf : cmdBuf )
print ( " RoPE done " )
print ( " Attention... " )
let attnOut = device . makeBuffer ( length : seqLen * nH * hDim * 4 ) !
let attnOut = device . makeBuffer ( length : seqLen * nH * hDim * 4 ) !
try bidirectionalAttention ( q : qBuf , k : kBuf , v : vBuf , output : attnOut , seqLen : seqLen , cmdBuf : cmdBuf )
try bidirectionalAttention ( q : qBuf , k : kBuf , v : vBuf , output : attnOut , seqLen : seqLen , cmdBuf : cmdBuf )
print ( " Attention done " )
print ( " O projection... " )
let h2 = device . makeBuffer ( length : seqLen * hs * 4 ) !
let h2 = device . makeBuffer ( length : seqLen * hs * 4 ) !
try matmulSeq ( input : attnOut , weight : oProjs [ layerIdx ] , output : h2 , m : seqLen , k : nH * hDim , n : hs , cmdBuf : cmdBuf )
try matmulSeq ( input : attnOut , weight : oProjs [ layerIdx ] , output : h2 , m : seqLen , k : nH * hDim , n : hs , cmdBuf : cmdBuf )
print ( " O done " )
print ( " Post-attn norm... " )
let h2n = try applyRmsNorm ( input : h2 , weight : layerNorms [ layerIdx ] [ 2 ] , count : seqLen * hs , cmdBuf : cmdBuf )
let h2n = try applyRmsNorm ( input : h2 , weight : layerNorms [ layerIdx ] [ 2 ] , count : seqLen * hs , cmdBuf : cmdBuf )
print ( " Add residual 1... " )
try eltwiseAdd ( a : resid , b : h2n , output : hidden , count : seqLen * hs , cmdBuf : cmdBuf )
try eltwiseAdd ( a : resid , b : h2n , output : hidden , count : seqLen * hs , cmdBuf : cmdBuf )
print ( " Pre-FF norm... " )
let h3 = try applyRmsNorm ( input : hidden , weight : layerNorms [ layerIdx ] [ 1 ] , count : seqLen * hs , cmdBuf : cmdBuf )
let h3 = try applyRmsNorm ( input : hidden , weight : layerNorms [ layerIdx ] [ 1 ] , count : seqLen * hs , cmdBuf : cmdBuf )
print ( " MLP gate/up... " )
let gate = device . makeBuffer ( length : seqLen * intermedi * 4 ) !
let gate = device . makeBuffer ( length : seqLen * intermedi * 4 ) !
let up = device . makeBuffer ( length : seqLen * intermedi * 4 ) !
let up = device . makeBuffer ( length : seqLen * intermedi * 4 ) !
try matmulSeq ( input : h3 , weight : gateProjs [ layerIdx ] , output : gate , m : seqLen , k : hs , n : intermedi , cmdBuf : cmdBuf )
try matmulSeq ( input : h3 , weight : gateProjs [ layerIdx ] , output : gate , m : seqLen , k : hs , n : intermedi , cmdBuf : cmdBuf )
print ( " Gate done " )
try matmulSeq ( input : h3 , weight : upProjs [ layerIdx ] , output : up , m : seqLen , k : hs , n : intermedi , cmdBuf : cmdBuf )
try matmulSeq ( input : h3 , weight : upProjs [ layerIdx ] , output : up , m : seqLen , k : hs , n : intermedi , cmdBuf : cmdBuf )
print ( " Up done " )
print ( " GELU mul... " )
let gated = device . makeBuffer ( length : seqLen * intermedi * 4 ) !
let gated = device . makeBuffer ( length : seqLen * intermedi * 4 ) !
try geluMul ( gate : gate , up : up , output : gated , count : seqLen * intermedi , cmdBuf : cmdBuf )
try geluMul ( gate : gate , up : up , output : gated , count : seqLen * intermedi , cmdBuf : cmdBuf )
print ( " GELU done " )
print ( " Down projection... " )
let h4 = device . makeBuffer ( length : seqLen * hs * 4 ) !
let h4 = device . makeBuffer ( length : seqLen * hs * 4 ) !
try matmulSeq ( input : gated , weight : downProjs [ layerIdx ] , output : h4 , m : seqLen , k : intermedi , n : hs , cmdBuf : cmdBuf )
try matmulSeq ( input : gated , weight : downProjs [ layerIdx ] , output : h4 , m : seqLen , k : intermedi , n : hs , cmdBuf : cmdBuf )
print ( " Down done " )
print ( " Post-FF norm... " )
let h4n = try applyRmsNorm ( input : h4 , weight : layerNorms [ layerIdx ] [ 3 ] , count : seqLen * hs , cmdBuf : cmdBuf )
let h4n = try applyRmsNorm ( input : h4 , weight : layerNorms [ layerIdx ] [ 3 ] , count : seqLen * hs , cmdBuf : cmdBuf )
print ( " Add residual 2... " )
try eltwiseAdd ( a : hidden , b : h4n , output : hidden , count : seqLen * hs , cmdBuf : cmdBuf )
try eltwiseAdd ( a : hidden , b : h4n , output : hidden , count : seqLen * hs , cmdBuf : cmdBuf )
print ( " Layer \( layerIdx ) complete " )
return hidden
return hidden
}
}