| 781 | |
| 782 | template<class precision=float> |
| 783 | void runTest(int version, size_t M, size_t K, size_t N, |
| 784 | std::unique_ptr<precision[]> &inputPtr, |
| 785 | std::unique_ptr<precision[]> &weightsPtr, |
| 786 | std::unique_ptr<precision[]> &outputPtr, |
| 787 | NumType numtype) { |
| 788 | if constexpr (std::is_same<precision, float>::value) { |
| 789 | assert(numtype == kf32); |
| 790 | } else if constexpr (std::is_same<precision, half>::value) { |
| 791 | assert(numtype == kf16); |
| 792 | } |
| 793 | |
| 794 | // Allocate GPU buffers and copy data |
| 795 | Context ctx = createContext( |
| 796 | {}, {}, |
| 797 | /*device descriptor, enabling f16 in WGSL*/ |
| 798 | { |
| 799 | .requiredFeatureCount = 1, |
| 800 | .requiredFeatures = std::array{WGPUFeatureName_ShaderF16}.data(), |
| 801 | }); |
| 802 | |
| 803 | Tensor input = createTensor(ctx, Shape{M, K}, numtype, inputPtr.get()); |
| 804 | Tensor weights = createTensor(ctx, Shape{N, K}, numtype, weightsPtr.get()); // column-major |
| 805 | |
| 806 | #ifdef METAL_PROFILER |
| 807 | constexpr size_t nIter = 1; |
| 808 | #else |
| 809 | constexpr size_t nIter = 30; |
| 810 | #endif |
| 811 | |
| 812 | // Initialize Kernel and bind GPU buffers |
| 813 | |
| 814 | |
| 815 | // pre-allocate for async dispatch |
| 816 | std::array<std::promise<void>, nIter> promises; |
| 817 | std::array<std::future<void>, nIter> futures; |
| 818 | std::array<Kernel, nIter> kernels; |
| 819 | std::array<Tensor, nIter> outputs; |
| 820 | for (int i = 0; i < nIter; i++) { |
| 821 | futures[i] = promises[i].get_future(); |
| 822 | outputs[i] = createTensor(ctx, Shape{M, N}, numtype); |
| 823 | kernels[i] = selectMatmul(ctx, version, {input, weights, outputs[i]}, M, K, N, numtype); |
| 824 | } |
| 825 | |
| 826 | #ifndef METAL_PROFILER |
| 827 | printf("[ Press enter to start tests ... ]\n"); |
| 828 | getchar(); |
| 829 | #endif |
| 830 | LOG(kDefLog, kInfo, "Dispatching Kernel version %d: %s, %d iterations ...", |
| 831 | version, versionToStr(version).c_str(), nIter); |
| 832 | |
| 833 | // Dispatch kernel nIter times |
| 834 | auto start = std::chrono::high_resolution_clock::now(); |
| 835 | for (int i = 0; i < nIter; i++) { |
| 836 | dispatchKernel(ctx, kernels[i], promises[i]); |
| 837 | } |
| 838 | for (int i = 0; i < nIter; i++) { |
| 839 | wait(ctx, futures[i]); |
| 840 | } |
no test coverage detected