diff --git a/tig-algorithms/src/vector_search/brute_force_bacalhau/README.md b/tig-algorithms/src/vector_search/brute_force_bacalhau/README.md new file mode 100644 index 00000000..bd9a4399 --- /dev/null +++ b/tig-algorithms/src/vector_search/brute_force_bacalhau/README.md @@ -0,0 +1,23 @@ +# TIG Code Submission + +## Submission Details + +* **Challenge Name:** vector_search +* **Algorithm Name:** brute_force_bacalhau +* **Copyright:** 2024 Louis Silva +* **Identity of Submitter:** Louis Silva +* **Identity of Creator of Algorithmic Method:** null +* **Unique Algorithm Identifier (UAI):** null + +## License + +The files in this folder are under the following licenses: +* TIG Benchmarker Outbound License +* TIG Commercial License +* TIG Inbound Game License +* TIG Innovator Outbound Game License +* TIG Open Data License +* TIG THV Game License + +Copies of the licenses can be obtained at: +https://github.com/tig-foundation/tig-monorepo/tree/main/docs/licenses \ No newline at end of file diff --git a/tig-algorithms/src/vector_search/brute_force_bacalhau/kernels.cu b/tig-algorithms/src/vector_search/brute_force_bacalhau/kernels.cu new file mode 100644 index 00000000..63172396 --- /dev/null +++ b/tig-algorithms/src/vector_search/brute_force_bacalhau/kernels.cu @@ -0,0 +1,19 @@ +/*! +Copyright 2024 Louis Silva + +Licensed under the TIG Inbound Game License v1.0 or (at your option) any later +version (the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at + +https://github.com/tig-foundation/tig-monorepo/tree/main/docs/licenses + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the specific +language governing permissions and limitations under the License. + */ + +extern "C" __global__ void do_nothing() +{ + // This kernel does nothing +} diff --git a/tig-algorithms/src/vector_search/brute_force_bacalhau/mod.rs b/tig-algorithms/src/vector_search/brute_force_bacalhau/mod.rs new file mode 100644 index 00000000..797c456b --- /dev/null +++ b/tig-algorithms/src/vector_search/brute_force_bacalhau/mod.rs @@ -0,0 +1,106 @@ +use anyhow::{anyhow, Result}; +use cudarc::{ + driver::{safe::LaunchConfig, CudaModule, CudaStream, PushKernelArg}, + runtime::sys::cudaDeviceProp, +}; +use serde_json::{Map, Value}; +use std::sync::Arc; +use tig_challenges::vector_search::{Challenge, Solution}; + +pub fn solve_challenge( + challenge: &Challenge, + save_solution: &dyn Fn(&Solution) -> anyhow::Result<()>, + hyperparameters: &Option>, + module: Arc, + stream: Arc, + prop: &cudaDeviceProp, +) -> anyhow::Result<()> { + Err(anyhow!("This algorithm is no longer compatible.")) +} + +// Old code that is no longer compatible +#[cfg(none)] +mod dead_code { + use anyhow::Result; + + use tig_challenges::vector_search::*; + + #[inline] + fn l2_norm(x: &[f32]) -> f32 { + x.iter().map(|&val| val * val).sum::().sqrt() + } + + #[inline] + fn euclidean_distance_with_precomputed_norm( + a_norm_sq: f32, + b_norm_sq: f32, + ab_dot_product: f32, + ) -> f32 { + (a_norm_sq + b_norm_sq - 2.0 * ab_dot_product).sqrt() + } + + pub fn solve_challenge(challenge: &Challenge) -> Result> { + let vector_database: &Vec> = &challenge.vector_database; + let query_vectors: &Vec> = &challenge.query_vectors; + let max_distance: f32 = challenge.max_distance; + + let mut indexes: Vec = Vec::with_capacity(query_vectors.len()); + let mut vector_norms_sq: Vec = Vec::with_capacity(vector_database.len()); + + let mut sum_norms_sq: f32 = 0.0; + let mut sum_squares: f32 = 0.0; + + for vector in vector_database { + let norm_sq: f32 = vector.iter().map(|&val| val * val).sum(); + sum_norms_sq += norm_sq.sqrt(); + sum_squares += norm_sq; + vector_norms_sq.push(norm_sq); + } + + let vector_norms_len: f32 = vector_norms_sq.len() as f32; + let std_dev: f32 = + ((sum_squares / vector_norms_len) - (sum_norms_sq / vector_norms_len).powi(2)).sqrt(); + let norm_threshold: f32 = 2.0 * std_dev; + + for query in query_vectors { + let query_norm_sq: f32 = query.iter().map(|&val| val * val).sum(); + + let mut closest_index: Option = None; + let mut closest_distance: f32 = f32::MAX; + + for (idx, vector) in vector_database.iter().enumerate() { + let vector_norm_sq = vector_norms_sq[idx]; + if ((vector_norm_sq.sqrt() - query_norm_sq.sqrt()).abs()) > norm_threshold { + continue; + } + + let ab_dot_product: f32 = query.iter().zip(vector).map(|(&x1, &x2)| x1 * x2).sum(); + let distance: f32 = euclidean_distance_with_precomputed_norm( + query_norm_sq, + vector_norm_sq, + ab_dot_product, + ); + + if distance <= max_distance { + closest_index = Some(idx); + break; // Early exit + } else if distance < closest_distance { + closest_index = Some(idx); + closest_distance = distance; + } + } + + if let Some(index) = closest_index { + indexes.push(index); + } else { + return Ok(None); + } + } + + Ok(Some(Solution { indexes })) + } +} + +pub fn help() { + println!("No help information available."); +} diff --git a/tig-algorithms/src/vector_search/mod.rs b/tig-algorithms/src/vector_search/mod.rs index ae3472ac..4990304e 100644 --- a/tig-algorithms/src/vector_search/mod.rs +++ b/tig-algorithms/src/vector_search/mod.rs @@ -24,7 +24,8 @@ // c004_a013 -// c004_a014 +pub mod brute_force_bacalhau; +pub use brute_force_bacalhau as c004_a014; // c004_a015