#include #include #include #include #include #include #include #include #include #include #include "vulkan_process_startup.h" namespace { constexpr uint32_t kDescriptorBytes = 32; static uint32_t next_random(uint32_t *state) { *state = *state * 1664525U + 1013904223U; return *state; } static std::vector descriptors(uint32_t count, uint32_t seed) { std::vector result(static_cast(count) * kDescriptorBytes); for (unsigned char &value : result) { value = static_cast(next_random(&seed) >> 24); } return result; } template static double milliseconds(Function function) { auto start = std::chrono::steady_clock::now(); function(); auto elapsed = std::chrono::steady_clock::now() - start; return std::chrono::duration(elapsed).count(); } static double median(std::vector values) { std::sort(values.begin(), values.end()); return values[values.size() / 2]; } static double benchmark_cpu(const std::vector &a, const std::vector &b, uint32_t count) { cv::Mat matrix_a(static_cast(count), kDescriptorBytes, CV_8U, const_cast(a.data())); cv::Mat matrix_b(static_cast(count), kDescriptorBytes, CV_8U, const_cast(b.data())); cv::BFMatcher matcher(cv::NORM_HAMMING, false); std::vector samples; std::vector> output; matcher.knnMatch(matrix_a, matrix_b, output, 2); for (int repetition = 0; repetition < 7; ++repetition) { samples.push_back(milliseconds([&] { output.clear(); matcher.knnMatch(matrix_a, matrix_b, output, 2); })); } return median(samples); } static bool benchmark_size(Lardon3DOrbVulkanBackend *backend, uint32_t count) { std::vector a = descriptors(count, 0x12340000U + count); std::vector b = descriptors(count, 0xabcd0000U + count); std::vector output(count); double cpu_ms = benchmark_cpu(a, b, count); std::vector samples; for (int repetition = 0; repetition < 8; ++repetition) { Lardon3DOrbVulkanResult result = LARDON3D_ORB_VULKAN_FAILED; double elapsed = milliseconds([&] { result = lardon3d_orb_vulkan_top2(backend, a.data(), count, b.data(), count, output.data(), output.size()); }); if (result != LARDON3D_ORB_VULKAN_OK) { return false; } if (repetition > 0) { samples.push_back(elapsed); } } Lardon3DOrbVulkanInfo info{}; if (!lardon3d_orb_vulkan_backend_info(backend, &info)) { return false; } std::printf("%u cpu_ms=%.3f vulkan_ms=%.3f submit_ms=%.3f gpu_ms=%.3f " "selector=%s\n", count, cpu_ms, median(samples), static_cast(info.dispatch_ns) / 1.0e6, static_cast(info.gpu_ns) / 1.0e6, lardon3d_orb_vulkan_should_use(count, count) ? "vulkan" : "cpu"); return true; } static bool benchmark_sustained(Lardon3DOrbVulkanBackend *backend) { const uint32_t sizes[] = {1024, 4096, 8192, 4096}; std::vector> inputs_a; std::vector> inputs_b; std::vector> outputs; for (uint32_t size : sizes) { inputs_a.push_back(descriptors(size, 0x98760000U + size)); inputs_b.push_back(descriptors(size, 0x67890000U + size)); outputs.emplace_back(size); } constexpr int repetitions = 5000; double elapsed = milliseconds([&] { for (int repetition = 0; repetition < repetitions; ++repetition) { size_t slot = static_cast(repetition) % std::size(sizes); uint32_t size = sizes[slot]; Lardon3DOrbVulkanResult result = lardon3d_orb_vulkan_top2( backend, inputs_a[slot].data(), size, inputs_b[slot].data(), size, outputs[slot].data(), outputs[slot].size()); if (result != LARDON3D_ORB_VULKAN_OK) { std::fprintf(stderr, "sustained dispatch failed at repetition %d\n", repetition); std::abort(); } } }); std::printf("sustained jobs=%d total_ms=%.3f pairs_per_second=%.3f\n", repetitions, elapsed, repetitions * 1000.0 / elapsed); return true; } } // namespace int main(int argc, char **argv) { if (!lardon3d_vulkan_evidence_process_startup()) { std::fprintf(stderr, "MESA_SHADER_CACHE_DISABLE must be true for safe CPU affinity\n"); return 1; } Lardon3DOrbVulkanBackend *backend = lardon3d_orb_vulkan_backend_create(); if (!backend) { return 1; } bool ok = true; const uint32_t sizes[] = {256, 512, 768, 1024, 4096, 8192}; for (uint32_t size : sizes) { ok = benchmark_size(backend, size) && ok; } if (argc == 2 && std::strcmp(argv[1], "--sustained") == 0) { ok = benchmark_sustained(backend) && ok; } Lardon3DOrbVulkanInfo info{}; if (lardon3d_orb_vulkan_backend_info(backend, &info)) { std::printf("device=%s workgroup=%u cold_init_ms=%.3f payload=%llu\n", info.device_name, info.workgroup_size, static_cast(info.initialization_ns) / 1.0e6, static_cast(info.permanent_payload_bytes)); } lardon3d_orb_vulkan_backend_destroy(backend); return ok ? 0 : 1; }