Skip to content

Commit

Permalink
add support for native code
Browse files Browse the repository at this point in the history
  • Loading branch information
germ3n committed Jan 20, 2025
1 parent 14373ff commit 823c1d6
Show file tree
Hide file tree
Showing 13 changed files with 909 additions and 78 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"tig-utils",
"tig-wasm",
"tig-worker",
"tig-native-wrapper",
]
exclude = []
resolver = "2"
Expand Down
35 changes: 26 additions & 9 deletions scripts/test_algorithm.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
REPO_DIR=$(dirname $(dirname "$(realpath "$0")"))
REPO_DIR=$(dirname $(dirname "$(realpath -- "$0")"))
TIG_WORKER_PATH="$REPO_DIR/target/release/tig-worker"

if [ ! -f $TIG_WORKER_PATH ]; then
Expand All @@ -8,17 +8,25 @@ if [ ! -f $TIG_WORKER_PATH ]; then
exit 1
fi


options=()
index=0
echo "Available WASMs:"
echo "Available algorithms:"
for w in $(find $REPO_DIR/tig-algorithms/wasm -name '*.wasm'); do
a_name=$(basename $w .wasm)
c_name=$(basename $(dirname $w))
echo "$index) $c_name/$a_name"
options+=("$c_name/$a_name")
echo "$index) $c_name/$a_name (WASM)"
options+=("wasm $c_name/$a_name")
index=$((index + 1))
done

for n in $(find $REPO_DIR/tig-algorithms/native -name '*.native'); do
a_name=$(basename $n .native)
c_name=$(basename $(dirname $n))
echo "$index) $c_name/$a_name (Native)"
options+=("native $c_name/$a_name")
index=$((index + 1))
done

echo "Don't see the algorithm you're looking for? Can run: git pull origin <challenge_name>/<algorithm_name> --no-edit"
read -p "Enter the index of the algorithm to test: " selected_index
if [[ $selected_index =~ ^[0-9]+$ ]] && [ "$selected_index" -ge 0 ] && [ "$selected_index" -lt "$index" ]; then
Expand All @@ -29,8 +37,9 @@ else
exit 1
fi

CHALLENGE=$(dirname $selected_option)
ALGORITHM=$(basename $selected_option)
BINARY_TYPE=$(echo $selected_option | cut -d' ' -f1)
CHALLENGE=$(echo $selected_option | cut -d' ' -f2 | cut -d'/' -f1)
ALGORITHM=$(echo $selected_option | cut -d' ' -f2 | cut -d'/' -f2)

case $CHALLENGE in
satisfiability)
Expand Down Expand Up @@ -92,7 +101,6 @@ get_closest_power_of_2() {
echo $p
}


SETTINGS="{\"challenge_id\":\"$CHALLENGE_ID\",\"difficulty\":$difficulty,\"algorithm_id\":\"\",\"player_id\":\"\",\"block_id\":\"\"}"
num_solutions=0
num_invalid=0
Expand All @@ -117,7 +125,16 @@ while [ $remaining_nonces -gt 0 ]; do
start_time=$(date +%s%3N)
stdout=$(mktemp)
stderr=$(mktemp)
./target/release/tig-worker compute_batch "$SETTINGS" "random_string" $current_nonce $nonces_to_compute $power_of_2_nonces $REPO_DIR/tig-algorithms/wasm/$CHALLENGE/$ALGORITHM.wasm --workers $nonces_to_compute >"$stdout" 2>"$stderr"

if [ "$BINARY_TYPE" = "wasm" ]; then
BINARY_PATH="$REPO_DIR/tig-algorithms/wasm/$CHALLENGE/$ALGORITHM.wasm"
BINARY_ARG="--wasm"
else
BINARY_PATH="$REPO_DIR/tig-algorithms/native/$CHALLENGE/$ALGORITHM.native"
BINARY_ARG="--native"
fi

./target/release/tig-worker compute_batch "$SETTINGS" "random_string" $current_nonce $nonces_to_compute $power_of_2_nonces $BINARY_ARG $BINARY_PATH --workers $nonces_to_compute >"$stdout" 2>"$stderr"
exit_code=$?
output_stdout=$(cat "$stdout")
output_stderr=$(cat "$stderr")
Expand Down
2 changes: 1 addition & 1 deletion tig-challenges/src/knapsack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl TryFrom<Map<String, Value>> for Solution {
}
}

#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Challenge {
pub seed: [u8; 32],
pub difficulty: Difficulty,
Expand Down
14 changes: 14 additions & 0 deletions tig-native-wrapper/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "tig-native-wrapper"
version = "0.1.0"
readme = "README.md"
license = "https://github.com/tig-foundation/tig-monorepo/tree/main/docs/agreements/end_user_license_agreement.pdf"
authors.workspace = true
repository.workspace = true
edition.workspace = true

[dependencies]
serde = { version = "1.0.196", features = ["derive"] }
serde_json = { version = "1.0.113" }
libloading = "0.8.6"
tig-challenges = { path = "../tig-challenges" }
17 changes: 17 additions & 0 deletions tig-native-wrapper/src/dylib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use {
libloading::{Library},
std::path::Path,
std::panic,
};

pub fn load_module(path: &Path) -> Result<Library, String>
{
let res = panic::catch_unwind(|| {
unsafe { Library::new(path) }
});

match res {
Ok(lib_result) => lib_result.map_err(|e| e.to_string()),
Err(_) => Err("Failed to load module".to_string())
}
}
70 changes: 70 additions & 0 deletions tig-native-wrapper/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
mod dylib;
mod solvers;

use {
tig_challenges::{
knapsack::{Challenge as KnapsackChallenge},
satisfiability::{Challenge as SatisfiabilityChallenge},
vector_search::{Challenge as VectorSearchChallenge},
vehicle_routing::{Challenge as VehicleRoutingChallenge},
},
};

macro_rules! handle_challenge {
($challenge_type:expr, $challenge_json:expr, $library_path:expr, $max_fuel:expr, $solver_fn:ident, $challenge:ty) => {
{
let challenge: $challenge = serde_json::from_str($challenge_json)
.map_err(|e| format!("Failed to parse challenge: {}", e))
.unwrap();

let result = solvers::$solver_fn(
$library_path.to_string(),
challenge,
Some($max_fuel)
);

if result.is_err()
{
println!("Error: {:?}", result.err().unwrap());
return;
}

let (solution, runtime_signature, fuel_remaining) = result.unwrap();
println!("{}", serde_json::json!({
"solution": solution,
"runtime_signature": runtime_signature,
"fuel_consumed": $max_fuel as i64 - fuel_remaining.max(0),
"nonce": 0,
}));
}
};
}

fn main()
{
let args: Vec<String> = std::env::args().collect();
if args.len() != 5
{
println!("Usage: {} <library_path> <challenge_type> <challenge_json> <max_fuel>", args[0]);
println!("Challenge types: knapsack, satisfiability, vector_search, vehicle_routing");
return;
}

let library_path = &args[1];
let challenge_type = &args[2];
let challenge_json = &args[3];
let max_fuel = args[4].parse::<u64>().unwrap();

match challenge_type.as_str()
{
"knapsack" => handle_challenge!(challenge_type, challenge_json, library_path, max_fuel, solve_knapsack, KnapsackChallenge),
"satisfiability" => handle_challenge!(challenge_type, challenge_json, library_path, max_fuel, solve_satisfiability, SatisfiabilityChallenge),
"vector_search" => handle_challenge!(challenge_type, challenge_json, library_path, max_fuel, solve_vector_search, VectorSearchChallenge),
"vehicle_routing" => handle_challenge!(challenge_type, challenge_json, library_path, max_fuel, solve_vehicle_routing, VehicleRoutingChallenge),
_ =>
{
println!("Invalid challenge type");
return;
}
}
}
48 changes: 48 additions & 0 deletions tig-native-wrapper/src/solvers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use {
std::path::PathBuf,
tig_challenges::{
knapsack::{Challenge as KnapsackChallenge, Solution as KnapsackSolution},
satisfiability::{Challenge as SatisfiabilityChallenge, Solution as SatisfiabilitySolution},
vector_search::{Challenge as VectorSearchChallenge, Solution as VectorSearchSolution},
vehicle_routing::{Challenge as VehicleRoutingChallenge, Solution as VehicleRoutingSolution},
},
crate::dylib::{load_module}
};

macro_rules! generate_solvers {
($(($name:ident, $challenge:ty, $solution:ty)),* $(,)?) => {
$(
pub fn $name(
library_path: String,
challenge: $challenge,
fuel: Option<u64>
) -> Result<($solution, u64, i64), String>
{
let library = load_module(&PathBuf::from(library_path))?;
let solve_fn = unsafe { library.get::<fn($challenge, Option<u64>) -> Option<$solution>>(b"entry_point").map_err(|e| e.to_string())? };

if fuel.is_some()
{
let fuel_remaining_ptr = unsafe { *library.get::<*mut i64>(b"__fuel_remaining").map_err(|e| e.to_string())? };
unsafe { *fuel_remaining_ptr = fuel.unwrap() as i64 };
}

let solution = solve_fn(challenge, fuel).ok_or_else(|| "Solver returned None".to_string())?;

let fuel_remaining_ptr = unsafe { *library.get::<*const i64>(b"__fuel_remaining").map_err(|e| e.to_string())? };
let runtime_signature_ptr = unsafe { *library.get::<*const u64>(b"__runtime_signature").map_err(|e| e.to_string())? };
let fuel_remaining = unsafe { *fuel_remaining_ptr };
let runtime_signature = unsafe { *runtime_signature_ptr };

Ok((solution, runtime_signature, fuel_remaining))
}
)*
};
}

generate_solvers!(
(solve_knapsack, KnapsackChallenge, KnapsackSolution),
(solve_satisfiability, SatisfiabilityChallenge, SatisfiabilitySolution),
(solve_vector_search, VectorSearchChallenge, VectorSearchSolution),
(solve_vehicle_routing, VehicleRoutingChallenge, VehicleRoutingSolution)
);
20 changes: 20 additions & 0 deletions tig-native/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "tig-native"
version = "0.1.0"
readme = "README.md"
license = "https://github.com/tig-foundation/tig-monorepo/tree/main/docs/agreements/end_user_license_agreement.pdf"

[lib]
crate-type = ["cdylib", "staticlib", "rlib"]

[dependencies]
tig-challenges = { path = "../tig-challenges" }

[workspace]

[features]
knapsack = []
vector_search = []
satisfiability = []
vehicle_routing = []
entry_point = []
Loading

0 comments on commit 823c1d6

Please sign in to comment.