| 172 | } |
| 173 | |
| 174 | int main() { |
| 175 | printf("\033[2J\033[1;1H"); |
| 176 | Context ctx = createContext(); |
| 177 | static constexpr size_t seqLen = 24; |
| 178 | static constexpr size_t batchSize = 1; |
| 179 | static constexpr size_t modelDim = 4; // 3072; |
| 180 | static constexpr size_t hiddenWidth = modelDim * 2; |
| 181 | static constexpr size_t qkvDim = 3; // 256; |
| 182 | static constexpr size_t nHeads = 8; |
| 183 | std::mt19937 gen(314); |
| 184 | |
| 185 | Transformer transformer; |
| 186 | Activations activations; |
| 187 | KVCache kvcache; |
| 188 | LOG(kDefLog, kInfo, "Initializing transformer, allocating GPU buffers ...\n"); |
| 189 | createTransformer(ctx, modelDim, qkvDim, nHeads, batchSize, seqLen, |
| 190 | hiddenWidth, transformer, activations, kvcache); |
| 191 | |
| 192 | std::array<float, modelDim> inputArr; |
| 193 | randint(inputArr, gen, -2, 2); |
| 194 | LOG(kDefLog, kInfo, "%s", |
| 195 | show<float>(inputArr.data(), 1, modelDim, "Input").c_str()); |
| 196 | Tensor input = createTensor(ctx, Shape{modelDim}, kf32, inputArr.data()); |
| 197 | |
| 198 | /* QKV Projection */ |
| 199 | |
| 200 | LOG(kDefLog, kInfo, "QKV Projection"); |
| 201 | { |
| 202 | KernelCode matmul = createMatmul(kShaderMatmul1, /*M*/ batchSize, |
| 203 | /*K*/ modelDim, /*N*/ 3 * qkvDim); |
| 204 | Kernel qkv = createKernel( |
| 205 | ctx, matmul, Bindings{input, transformer.qkv, activations.qkv}, |
| 206 | /*nthreads*/ {modelDim, 1, 1}); |
| 207 | std::promise<void> promise; |
| 208 | std::future<void> future = promise.get_future(); |
| 209 | dispatchKernel(ctx, qkv, promise); |
| 210 | wait(ctx, future); |
| 211 | std::array<float, 3 * qkvDim> outputArr; |
| 212 | toCPU(ctx, activations.qkv, outputArr.data(), sizeof(outputArr)); |
| 213 | LOG(kDefLog, kInfo, "Output: %s", |
| 214 | show<float>(outputArr.data(), 1, 3 * qkvDim, "QKV Output").c_str()); |
| 215 | std::array<float, 3 * qkvDim> outputRefArr; |
| 216 | std::array<float, modelDim * 3 * qkvDim> weightsArr; |
| 217 | toCPU(ctx, transformer.qkv, weightsArr.data(), sizeof(weightsArr)); |
| 218 | ref::matmul_forward_cpu( |
| 219 | outputRefArr.data(), inputArr.data(), weightsArr.data(), nullptr, |
| 220 | /* batch */ 1, /* T */ 1, /* C */ modelDim, /* OC */ 3 * qkvDim); |
| 221 | LOG(kDefLog, kInfo, "Reference Output: %s", |
| 222 | show<float>(outputRefArr.data(), 1, 3 * qkvDim, |
| 223 | "QKV Output (Reference)") |
| 224 | .c_str()); |
| 225 | LOG(kDefLog, kInfo, |
| 226 | isclose(outputArr.data(), outputRefArr.data(), 3 * qkvDim) ? "PASS" |
| 227 | : "FAIL"); |
| 228 | } |
| 229 | |
| 230 | /* QK Dot Products */ |
| 231 |
nothing calls this directly
no test coverage detected