#ifndef FACE_CLUSTERING_KNN_OPENCL_H #define FACE_CLUSTERING_KNN_OPENCL_H #include #include #include #include namespace face_knn { constexpr std::uint32_t invalid_index = 0xffffffffu; struct Neighbor { float score = 0.0f; std::uint32_t index = invalid_index; }; struct SearchOptions { std::uint32_t dimension = 128; std::uint32_t top_k = 1; std::uint32_t lanes_per_query = 8; std::size_t chunk_size = 50000; std::string kernel_path; }; struct SearchOutput { std::size_t query_count = 0; std::size_t database_count = 0; std::uint32_t dimension = 0; std::uint32_t top_k = 0; std::string backend; std::string device_name; double elapsed_ms = 0.0; /* * Layout: * * neighbors[ * query_index * top_k * + neighbor_position * ] */ std::vector neighbors; }; struct ValidationResult { std::size_t positions = 0; std::size_t exact_index_matches = 0; std::size_t decision_matches = 0; float maximum_score_error = 0.0f; bool exact_indices = false; bool decisions_equal = false; }; void validate_input( const std::vector& database, const std::vector& queries, std::size_t database_count, std::size_t query_count, const SearchOptions& options); SearchOutput search_cpu( const std::vector& database, const std::vector& queries, std::size_t database_count, std::size_t query_count, const SearchOptions& options); SearchOutput search_opencl( const std::vector& database, const std::vector& queries, std::size_t database_count, std::size_t query_count, const SearchOptions& options); ValidationResult compare_outputs( const SearchOutput& expected, const SearchOutput& actual, float score_tolerance, float recognition_threshold); std::vector query_neighbors( const SearchOutput& output, std::size_t query_index); std::vector exclude_neighbor( const std::vector& neighbors, std::uint32_t excluded_index); } // namespace face_knn #endif