| 216 | } |
| 217 | |
| 218 | void testSoftmax(Context &ctx) { |
| 219 | |
| 220 | struct SoftmaxParam { |
| 221 | uint32_t N; |
| 222 | uint32_t C; |
| 223 | }; |
| 224 | static constexpr size_t B = 6; // batch size |
| 225 | static constexpr size_t T = 8; // token index |
| 226 | static constexpr size_t C = 3072; // input channels |
| 227 | std::array<float, B * T * C> inputArr; |
| 228 | std::array<float, B * T * C> outputArr; |
| 229 | std::mt19937 gen(31415); |
| 230 | randint(inputArr, gen, 0, 3); |
| 231 | Tensor input = createTensor(ctx, {B * T, C}, kf32, inputArr.data()); |
| 232 | Tensor output = createTensor(ctx, {B * T, C}, kf32, outputArr.data()); |
| 233 | LOG(kDefLog, kInfo, "num threads: %d", B * T); |
| 234 | std::promise<void> promise; |
| 235 | std::future<void> future = promise.get_future(); |
| 236 | Kernel op = createKernel( |
| 237 | ctx, {kShaderSoftmax1, 256, kf32}, Bindings{input, output}, |
| 238 | Shape{cdiv(B * T, 256), 1, 1}, SoftmaxParam{B * T, C}); |
| 239 | dispatchKernel(ctx, op, promise); |
| 240 | wait(ctx, future); |
| 241 | toCPU(ctx, output, outputArr.data(), sizeof(outputArr)); |
| 242 | LOG(kDefLog, kInfo, "%s", |
| 243 | show<float, B * T, C>(inputArr, "Softmax Input").c_str()); |
| 244 | LOG(kDefLog, kInfo, "%s", |
| 245 | show<float, B * T, C>(outputArr, "Softmax Output").c_str()); |
| 246 | std::array<float, B * T * C> refOutputArr; |
| 247 | ref::softmax_forward_cpu(refOutputArr.data(), inputArr.data(), B * T, C); |
| 248 | LOG(kDefLog, kInfo, "%s", |
| 249 | show<float, B * T, C>(refOutputArr, "Softmax reference Output").c_str()); |
| 250 | |
| 251 | LOG(kDefLog, kInfo, "number of elements: %d", B * T * C); |
| 252 | bool passed = isclose(outputArr.data(), refOutputArr.data(), B * T * C); |
| 253 | assert(passed); |
| 254 | LOG(kDefLog, kInfo, "Softmax passed? %d", passed); |
| 255 | LOG(kDefLog, kInfo, "Done with Softmax Test"); |
| 256 | } |
| 257 | |
| 258 | void testAttention(Context &ctx) { |
| 259 | static constexpr size_t B = 6; |
no test coverage detected