Rework architecture so each challenge has separate runtime & docker.
Some checks are pending
Test Workspace / Test Workspace (push) Waiting to run

This commit is contained in:
FiveMovesAhead 2025-06-04 11:06:26 +01:00
parent 7ebad69cf7
commit 89d86f9deb
17 changed files with 447 additions and 315 deletions

View File

@ -1,8 +1,13 @@
ARG BASE_IMAGE=ubuntu:24.04
ARG CHALLENGE
# Development environment stage
FROM ${BASE_IMAGE}
ARG CHALLENGE
ENV CHALLENGE=${CHALLENGE}
RUN if [ -z "$CHALLENGE" ]; then echo "Error: '--build-arg CHALLENGE' must be set." && exit 1; fi
RUN ARCH=$(uname -m) && \
if [ "$ARCH" != "aarch64" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "amd64" ] && [ "$ARCH" != "x86_64" ]; then \
echo "Unsupported architecture: $ARCH. Must be 'aarch64', 'arm64', 'amd64', or 'x86_64'." && exit 1; \
@ -26,9 +31,8 @@ RUN ARCH=$(uname -m) && \
rustup component add rust-src && \
rustup target add $RUST_TARGET && \
RUST_LIBDIR=$(rustc --print target-libdir --target=$RUST_TARGET) && \
ln -s $RUST_LIBDIR /usr/local/lib/rust && \
echo "export LD_LIBRARY_PATH=\"${LD_LIBRARY_PATH}:/usr/local/lib/rust\"" >> /etc/bash.bashrc && \
echo "export RUST_TARGET=\"${RUST_TARGET}\"" >> /etc/bash.bashrc
ln -s $RUST_LIBDIR /usr/local/lib/rust
ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/lib/rust"
RUN ARCH=$(uname -m) && \
LLVM_URL=$(if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then \
@ -42,25 +46,20 @@ RUN ARCH=$(uname -m) && \
rm -rf llvm.tar.zst && \
ln -s /opt/llvm/bin/* /usr/local/bin/
COPY scripts/ /usr/local/bin/tig-scripts/
COPY tig-binary/scripts/ /usr/local/bin/tig-scripts/
RUN chmod +x /usr/local/bin/tig-scripts/*
ENV PATH="/usr/local/bin/tig-scripts:${PATH}"
COPY . /tmp/tig-monorepo
WORKDIR /tmp/tig-monorepo
RUN if command -v nvcc > /dev/null 2>&1; then \
cargo build -r -p tig-runtime --features cuda && \
cargo build -r -p tig-verifier --features cuda; \
else \
cargo build -r -p tig-runtime && \
cargo build -r -p tig-verifier; \
fi && \
RUN cargo build -r -p tig-runtime --features $CHALLENGE && \
cargo build -r -p tig-verifier --features $CHALLENGE && \
mv target/release/tig-runtime /usr/local/bin/ && \
mv target/release/tig-verifier /usr/local/bin/ && \
chmod +x /usr/local/bin/tig-runtime && \
chmod +x /usr/local/bin/tig-verifier && \
rm -rf tig-monorepo
COPY scripts/ /usr/local/bin/tig-scripts/
COPY tig-binary/scripts/ /usr/local/bin/tig-scripts/
RUN chmod +x /usr/local/bin/tig-scripts/*
ENV PATH="/usr/local/bin/tig-scripts:${PATH}"
WORKDIR /app

View File

@ -1,27 +1,28 @@
ARG BASE_IMAGE=ubuntu:24.04
ARG DEV_IMAGE=ghcr.io/tig-foundation/tig-monorepo/dev
ARG CHALLENGE
FROM ${DEV_IMAGE} AS dev
FROM ghcr.io/tig-foundation/tig-monorepo/${CHALLENGE}/dev AS dev
FROM ${BASE_IMAGE}
ARG CHALLENGE
ENV CHALLENGE=${CHALLENGE}
RUN if [ -z "$CHALLENGE" ]; then echo "Error: '--build-arg CHALLENGE' must be set." && exit 1; fi
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y python3 python3-pip
RUN pip3 install requests --break-system-packages
COPY scripts/ /usr/local/bin/tig-scripts/
RUN chmod +x /usr/local/bin/tig-scripts/*
ENV PATH="/usr/local/bin/tig-scripts:${PATH}"
COPY --from=dev /usr/local/bin/tig-runtime /usr/local/bin/tig-runtime
COPY --from=dev /usr/local/bin/tig-verifier /usr/local/bin/tig-verifier
COPY --from=dev /usr/local/lib/rust /usr/local/lib/rust
RUN chmod +x /usr/local/bin/tig-runtime && \
chmod +x /usr/local/bin/tig-verifier && \
echo "export LD_LIBRARY_PATH=\"${LD_LIBRARY_PATH}:/usr/local/lib/rust\"" >> /etc/bash.bashrc
RUN apt update && apt install -y python3 python3-pip
RUN pip3 install blake3 requests randomname --break-system-packages
COPY scripts/ /usr/local/bin/tig-scripts/
RUN chmod +x /usr/local/bin/tig-scripts/*
ENV PATH="/usr/local/bin/tig-scripts:${PATH}"
COPY tig-benchmarker /app
chmod +x /usr/local/bin/tig-verifier
ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/lib/rust"
WORKDIR /app

View File

@ -7,9 +7,13 @@ import requests
import sys
import tarfile
CHALLENGE = os.getenv("CHALLENGE")
if CHALLENGE is None:
print("CHALLENGE environment variable must be set!")
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description='TIG Algorithm Downloader')
parser.add_argument('challenge', help="Challenge name or id")
parser.add_argument('algorithm', help="Algorithm name or id")
parser.add_argument('--out', default="tig-algorithms/lib", help="Output directory (default: tig-algorithms/lib)")
parser.add_argument('--testnet', action='store_true', help="Use testnet API")
@ -26,12 +30,12 @@ def main():
c_id = next(
(
c['id'] for c in challenges
if c['details']['name'] == args.challenge or c['id'] == args.challenge
if c['details']['name'] == CHALLENGE
),
None
)
if c_id is None:
print(f"Challenge '{args.challenge}' not found.")
print(f"Challenge '{CHALLENGE}' not found.")
sys.exit(1)
a_id = next(
@ -44,7 +48,7 @@ def main():
None
)
if a_id is None:
print(f"Algorithm '{args.algorithm}' not found for challenge '{args.challenge}'.")
print(f"Algorithm '{args.algorithm}' not found for challenge '{CHALLENGE}'.")
sys.exit(1)
download_url = download_urls.get(a_id)
@ -54,7 +58,7 @@ def main():
print(f"Downloading algorithm '{args.algorithm}' from {download_url}...")
resp = requests.get(download_url, stream=True)
output_dir = f"{args.out}/{args.challenge}"
output_dir = f"{args.out}/{CHALLENGE}"
os.makedirs(output_dir, exist_ok=True)
with tarfile.open(fileobj=io.BytesIO(resp.content), mode='r:gz') as tar:
tar.extractall(path=output_dir)

View File

@ -1,15 +1,17 @@
#!/usr/bin/env python3
import argparse
import io
import os
import requests
import sys
import tarfile
CHALLENGE = os.getenv("CHALLENGE")
if CHALLENGE is None:
print("CHALLENGE environment variable must be set!")
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description='TIG Algorithm Lister')
parser.add_argument('challenge', help="Challenge name or id")
parser.add_argument('--testnet', action='store_true', help="Use testnet API")
args = parser.parse_args()
@ -24,12 +26,12 @@ def main():
c_id = next(
(
c['id'] for c in challenges
if c['details']['name'] == args.challenge or c['id'] == args.challenge
if c['details']['name'] == CHALLENGE
),
None
)
if c_id is None:
print(f"Challenge '{args.challenge}' not found.")
print(f"Challenge '{CHALLENGE}' not found.")
sys.exit(1)
algorithms = sorted([

View File

@ -37,6 +37,11 @@ elif (VISIBLE_GPUS := os.environ.get("CUDA_VISIBLE_DEVICES", None)) is None:
else:
VISIBLE_GPUS = list(map(int, VISIBLE_GPUS.split(",")))
CHALLENGE = os.getenv("CHALLENGE")
if CHALLENGE is None:
print("CHALLENGE environment variable must be set!")
sys.exit(1)
def now():
return int(time.time() * 1000)
@ -44,7 +49,6 @@ def now():
if __name__ == "__main__":
tig_runtime_path = shutil.which("tig-runtime")
parser = argparse.ArgumentParser(description="TIG Algorithm Tester")
parser.add_argument("challenge", type=str, help="Challenge name")
parser.add_argument("algorithm", type=str, help="Algorithm name")
parser.add_argument("difficulty", type=str, help="JSON string of difficulty")
parser.add_argument("--tig_runtime_path", type=str, default=tig_runtime_path, help=f"Path to tig-runtime executable (default: {tig_runtime_path})")
@ -58,8 +62,8 @@ if __name__ == "__main__":
args = parser.parse_args()
so_path = f"{args.lib_dir}/{args.challenge}/{CPU_ARCH}/{args.algorithm}.so"
ptx_path = f"{args.lib_dir}/{args.challenge}/ptx/{args.algorithm}.ptx"
so_path = f"{args.lib_dir}/{CHALLENGE}/{CPU_ARCH}/{args.algorithm}.so"
ptx_path = f"{args.lib_dir}/{CHALLENGE}/ptx/{args.algorithm}.ptx"
if not os.path.exists(so_path):
print(
@ -93,10 +97,7 @@ f"""Library not found at {so_path}:
"hypergraph": "c005",
"optimiser": "c006",
}
challenge_id = challenge_ids.get(args.challenge, None)
if challenge_id is None:
print(f"Unknown challenge '{args.challenge}'. Choices: ({', '.join(challenge_ids.keys())})")
sys.exit(1)
challenge_id = challenge_ids[CHALLENGE]
settings = {"algorithm_id": "", "challenge_id": challenge_id, "difficulty": difficulty, "block_id": "", "player_id": ""}
pool = ThreadPoolExecutor(max_workers=args.workers + 1)

View File

@ -23,4 +23,14 @@ tig-challenges = { path = "../tig-challenges" }
crate-type = ["cdylib", "rlib"]
[features]
cuda = ["cudarc", "tig-challenges/cuda"]
cuda = ["cudarc"]
c001 = ["tig-challenges/c001"]
satisfiability = ["c001"]
c002 = ["tig-challenges/c002"]
vehicle_routing = ["c002"]
c003 = ["tig-challenges/c003"]
knapsack = ["c003"]
c004 = ["cuda", "tig-challenges/c004"]
vector_search = ["c004"]
c005 = ["cuda", "tig-challenges/c005"]
hypergraph = ["c005"]

View File

@ -11,18 +11,23 @@ pub(crate) type HashSet<T> = std::collections::HashSet<T, RandomState>;
pub const BUILD_TIME_PATH: &str = env!("CARGO_MANIFEST_DIR");
pub mod knapsack;
pub use knapsack as c003;
#[cfg(feature = "c001")]
pub mod satisfiability;
#[cfg(feature = "c001")]
pub use satisfiability as c001;
#[cfg(feature = "c002")]
pub mod vehicle_routing;
#[cfg(feature = "c002")]
pub use vehicle_routing as c002;
#[cfg(feature = "cuda")]
#[cfg(feature = "c003")]
pub mod knapsack;
#[cfg(feature = "c003")]
pub use knapsack as c003;
#[cfg(feature = "c004")]
pub mod vector_search;
#[cfg(feature = "cuda")]
#[cfg(feature = "c004")]
pub use vector_search as c004;
#[cfg(feature = "cuda")]
#[cfg(feature = "c005")]
pub mod hypergraph;
#[cfg(feature = "cuda")]
#[cfg(feature = "c005")]
pub use hypergraph as c005;

View File

@ -19,4 +19,14 @@ tig-algorithms = { path = "../tig-algorithms" }
[features]
entry_point = []
cuda = ["cudarc", "tig-algorithms/cuda", "tig-challenges/cuda"]
cuda = ["cudarc"]
c001 = ["tig-algorithms/c001", "tig-challenges/c001"]
satisfiability = ["c001"]
c002 = ["tig-algorithms/c002", "tig-challenges/c002"]
vehicle_routing = ["c002"]
c003 = ["tig-algorithms/c003", "tig-challenges/c003"]
knapsack = ["c003"]
c004 = ["cuda", "tig-algorithms/c004", "tig-challenges/c004"]
vector_search = ["c004"]
c005 = ["cuda", "tig-algorithms/c005", "tig-challenges/c005"]
hypergraph = ["c005"]

View File

@ -0,0 +1,48 @@
#!/bin/bash
set -e
# Check if CHALLENGE environment variable is set
if [ -z "$CHALLENGE" ]; then
echo "Error: CHALLENGE environment variable is not set."
exit 1
fi
# Check if ALGORITHM argument is provided
if [ -z "$1" ]; then
echo "Error: ALGORITHM argument is required."
echo "Usage: $0 <ALGORITHM>"
exit 1
fi
ALGORITHM="$1"
# Match CHALLENGE value
case "$CHALLENGE" in
satisfiability)
echo "Building ALGORITHM '$ALGORITHM' for CHALLENGE 'satisfiability'"
build_so $ALGORITHM
;;
vehicle_routing)
echo "Building ALGORITHM '$ALGORITHM' for CHALLENGE 'vehicle_routing'"
build_so $ALGORITHM
;;
knapsack)
echo "Building ALGORITHM '$ALGORITHM' for CHALLENGE 'knapsack'"
build_so $ALGORITHM
;;
vector_search)
echo "Building ALGORITHM '$ALGORITHM' for CHALLENGE 'vector_search'"
build_so $ALGORITHM
build_ptx $ALGORITHM
;;
hypergraph)
echo "Building ALGORITHM '$ALGORITHM' for CHALLENGE 'hypergraph'"
build_so $ALGORITHM
build_ptx $ALGORITHM
;;
*)
echo "Error: Invalid CHALLENGE value. Must be one of: satisfiability, knapsack, vehicle_routing, vector_search, hypergraph"
exit 1
;;
esac

View File

@ -3,11 +3,15 @@
import argparse
import os
import re
import shutil
import subprocess
import sys
import tempfile
CHALLENGE = os.getenv("CHALLENGE")
if CHALLENGE is None:
print("CHALLENGE environment variable must be set!")
sys.exit(1)
# Import the dictionary from ptx_instructions.py
instruction_fuel_cost = {
'add.u32': 2,
@ -232,12 +236,11 @@ $NORMAL_EXIT:
def main():
parser = argparse.ArgumentParser(description='Compile PTX with injected runtime signature')
parser.add_argument('challenge', help='Challenge name')
parser.add_argument('algorithm', help='Algorithm name')
args = parser.parse_args()
print(f"Compiling .ptx for {args.challenge}/{args.algorithm}")
print(f"Compiling .ptx for {CHALLENGE}/{args.algorithm}")
framework_cu = "tig-binary/src/framework.cu"
if not os.path.exists(framework_cu):
@ -245,14 +248,14 @@ def main():
f"Framework code does not exist @ '{framework_cu}'. This script must be run from the root of tig-monorepo"
)
challenge_cu = f"tig-challenges/src/{args.challenge}.cu"
challenge_cu = f"tig-challenges/src/{CHALLENGE}.cu"
if not os.path.exists(challenge_cu):
raise FileNotFoundError(
f"Challenge code does not exist @ '{challenge_cu}'. Is the challenge name correct?"
)
algorithm_cu = f"tig-algorithms/src/{args.challenge}/{args.algorithm}.cu"
algorithm_cu2 = f"tig-algorithms/src/{args.challenge}/{args.algorithm}/benchmarker_outbound.cu"
algorithm_cu = f"tig-algorithms/src/{CHALLENGE}/{args.algorithm}.cu"
algorithm_cu2 = f"tig-algorithms/src/{CHALLENGE}/{args.algorithm}/benchmarker_outbound.cu"
if not os.path.exists(algorithm_cu) and not os.path.exists(algorithm_cu2):
raise FileNotFoundError(
f"Algorithm code does not exist @ '{algorithm_cu}' or '{algorithm_cu2}'. Is the algorithm name correct?"
@ -295,10 +298,8 @@ def main():
parsed = parse_ptx_code(ptx_code)
modified_code = inject_fuel_and_runtime_sig(parsed, kernels_to_ignore)
output_path = f"tig-algorithms/lib/{args.challenge}/ptx/{args.algorithm}.ptx"
output_path = f"tig-algorithms/lib/{CHALLENGE}/ptx/{args.algorithm}.ptx"
os.makedirs(os.path.dirname(output_path), exist_ok=True)
# with open(output_path, 'w') as f:
# f.writelines(ptx_code)
with open(output_path, 'w') as f:
f.writelines(modified_code)
print(f"Wrote ptx to {output_path}")

View File

@ -2,55 +2,34 @@
set -e
CUDA=false
if [ $# -lt 2 ]; then
echo "Error: Missing required arguments"
echo "Usage: $0 CHALLENGE ALGORITHM [--cuda]"
echo "Example: $0 knapsack dynamic"
echo "Example with CUDA: $0 knapsack dynamic --cuda"
exit 1
fi
CHALLENGE="$1"
ALGORITHM="$2"
shift 2
while [ $# -gt 0 ]; do
case "$1" in
--cuda)
CUDA=true
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 CHALLENGE ALGORITHM [--cuda]"
exit 1
;;
esac
shift
done
# Check if CHALLENGE environment variable is set
if [ -z "$CHALLENGE" ]; then
echo "Error: CHALLENGE argument is empty"
echo "Error: CHALLENGE environment variable is not set."
exit 1
fi
if [ -z "$ALGORITHM" ]; then
echo "Error: ALGORITHM argument is empty"
# Check if ALGORITHM argument is provided
if [ -z "$1" ]; then
echo "Error: ALGORITHM argument is required."
echo "Usage: $0 <ALGORITHM>"
exit 1
fi
ALGORITHM="$1"
echo "Compiling .so for $CHALLENGE/$ALGORITHM"
cp tig-binary/src/entry_point_template.rs tig-binary/src/entry_point.rs
sed -i "s/{CHALLENGE}/$CHALLENGE/g" tig-binary/src/entry_point.rs
sed -i "s/{ALGORITHM}/$ALGORITHM/g" tig-binary/src/entry_point.rs
if [ "$CUDA" = true ]; then
FEATURES="entry_point cuda"
else
FEATURES="entry_point"
fi
FEATURES="entry_point $CHALLENGE"
ARCH=$(uname -m)
RUST_TARGET=$(if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
echo "aarch64-unknown-linux-gnu";
else
echo "x86_64-unknown-linux-gnu";
fi)
RUSTFLAGS="--emit=llvm-ir -C embed-bitcode=yes -C codegen-units=1 -C opt-level=3 -C lto=no -C debuginfo=2 -C relocation-model=pic" \
cargo +nightly-2025-02-10 build \
-p tig-binary \

View File

@ -23,3 +23,13 @@ statrs = { version = "0.18.0" }
[features]
cuda = ["cudarc"]
c001 = []
satisfiability = ["c001"]
c002 = []
vehicle_routing = ["c002"]
c003 = []
knapsack = ["c003"]
c004 = ["cuda"]
vector_search = ["c004"]
c005 = ["cuda"]
hypergraph = ["c005"]

View File

@ -1,17 +1,22 @@
pub const BUILD_TIME_PATH: &str = env!("CARGO_MANIFEST_DIR");
pub mod knapsack;
pub use knapsack as c003;
#[cfg(feature = "c001")]
pub mod satisfiability;
#[cfg(feature = "c001")]
pub use satisfiability as c001;
#[cfg(feature = "c002")]
pub mod vehicle_routing;
#[cfg(feature = "c002")]
pub use vehicle_routing as c002;
#[cfg(feature = "cuda")]
#[cfg(feature = "c003")]
pub mod knapsack;
#[cfg(feature = "c003")]
pub use knapsack as c003;
#[cfg(feature = "c004")]
pub mod vector_search;
#[cfg(feature = "cuda")]
#[cfg(feature = "c004")]
pub use vector_search as c004;
#[cfg(feature = "cuda")]
#[cfg(feature = "c005")]
pub mod hypergraph;
#[cfg(feature = "cuda")]
#[cfg(feature = "c005")]
pub use hypergraph as c005;

View File

@ -21,4 +21,14 @@ tig-structs = { path = "../tig-structs" }
tig-utils = { path = "../tig-utils" }
[features]
cuda = ["cudarc", "tig-challenges/cuda"]
cuda = ["cudarc"]
c001 = ["tig-challenges/c001"]
satisfiability = ["c001"]
c002 = ["tig-challenges/c002"]
vehicle_routing = ["c002"]
c003 = ["tig-challenges/c003"]
knapsack = ["c003"]
c004 = ["cuda", "tig-challenges/c004"]
vector_search = ["c004"]
c005 = ["cuda", "tig-challenges/c005"]
hypergraph = ["c005"]

View File

@ -51,7 +51,6 @@ fn cli() -> Command {
)
.arg(
arg!(--gpu [GPU] "Which GPU device to use")
.default_value("0")
.value_parser(clap::value_parser!(usize)),
)
}
@ -68,7 +67,7 @@ fn main() {
*matches.get_one::<u64>("fuel").unwrap(),
matches.get_one::<PathBuf>("output").cloned(),
matches.get_one::<bool>("compress").unwrap().clone(),
matches.get_one::<usize>("gpu").unwrap().clone(),
matches.get_one::<usize>("gpu").cloned(),
) {
eprintln!("Error: {}", e);
std::process::exit(1);
@ -80,13 +79,11 @@ pub fn compute_solution(
rand_hash: String,
nonce: u64,
library_path: PathBuf,
#[cfg(feature = "cuda")] ptx_path: Option<PathBuf>,
#[cfg(not(feature = "cuda"))] _ptx_path: Option<PathBuf>,
ptx_path: Option<PathBuf>,
max_fuel: u64,
output_file: Option<PathBuf>,
compress: bool,
#[cfg(feature = "cuda")] gpu_device: usize,
#[cfg(not(feature = "cuda"))] _gpu_device: usize,
gpu_device: Option<usize>,
) -> Result<()> {
let settings = load_settings(&settings);
let seed = settings.calc_seed(&rand_hash, nonce);
@ -97,7 +94,12 @@ pub fn compute_solution(
let runtime_signature_ptr = unsafe { *library.get::<*mut u64>(b"__runtime_signature")? };
unsafe { *runtime_signature_ptr = u64::from_be_bytes(seed[0..8].try_into().unwrap()) };
let (fuel_consumed, runtime_signature, solution, invalid_reason) = 'out_of_fuel: {
let (fuel_consumed, runtime_signature, solution, invalid_reason): (
u64,
u64,
Solution,
Option<String>,
) = 'out_of_fuel: {
macro_rules! dispatch_challenge {
($c:ident, cpu) => {{
// library function may exit 87 if it runs out of fuel
@ -138,11 +140,6 @@ pub fn compute_solution(
}};
($c:ident, gpu) => {{
#[cfg(not(feature = "cuda"))]
panic!("tig-runtime was not compiled with '--features cuda'");
#[cfg(feature = "cuda")]
{
if ptx_path.is_none() {
panic!("PTX file is required for GPU challenges.");
}
@ -154,9 +151,7 @@ pub fn compute_solution(
Arc<CudaModule>,
Arc<CudaStream>,
&cudaDeviceProp,
) -> Result<Option<$c::Solution>, String>>(
b"entry_point"
)?
) -> Result<Option<$c::Solution>, String>>(b"entry_point")?
};
let gpu_fuel_scale = 20; // scale fuel to loosely align with CPU
@ -165,6 +160,11 @@ pub fn compute_solution(
let max_fuel_hex = format!("0x{:016x}", max_fuel * gpu_fuel_scale);
let modified_ptx = ptx_content.replace("0xdeadbeefdeadbeef", &max_fuel_hex);
let num_gpus = CudaContext::device_count()?;
if num_gpus == 0 {
panic!("No CUDA devices found");
}
let gpu_device = gpu_device.unwrap_or((nonce % num_gpus as u64) as usize);
let ptx = Ptx::from_src(modified_ptx);
let ctx = CudaContext::new(gpu_device)?;
ctx.set_blocking_synchronize()?;
@ -195,8 +195,7 @@ pub fn compute_solution(
.launch(cfg)?;
}
let result =
solve_challenge_fn(&challenge, module.clone(), stream.clone(), &prop);
let result = solve_challenge_fn(&challenge, module.clone(), stream.clone(), &prop);
if result
.as_ref()
.is_err_and(|e| e.contains("ran out of fuel"))
@ -249,12 +248,7 @@ pub fn compute_solution(
.as_object()
.unwrap()
.to_owned(),
match challenge.verify_solution(
&s,
module.clone(),
stream.clone(),
&prop,
) {
match challenge.verify_solution(&s, module.clone(), stream.clone(), &prop) {
Ok(_) => None,
Err(e) => Some(e.to_string()),
},
@ -263,16 +257,40 @@ pub fn compute_solution(
};
(fuel_consumed, runtime_signature, solution, invalid_reason)
}
}};
}
match settings.challenge_id.as_str() {
"c001" => dispatch_challenge!(c001, cpu),
"c002" => dispatch_challenge!(c002, cpu),
"c003" => dispatch_challenge!(c003, cpu),
"c004" => dispatch_challenge!(c004, gpu),
"c005" => dispatch_challenge!(c005, gpu),
"c001" => {
#[cfg(not(feature = "c001"))]
panic!("tig-runtime was not compiled with '--features c001'");
#[cfg(feature = "c001")]
dispatch_challenge!(c001, cpu)
}
"c002" => {
#[cfg(not(feature = "c002"))]
panic!("tig-runtime was not compiled with '--features c002'");
#[cfg(feature = "c002")]
dispatch_challenge!(c002, cpu)
}
"c003" => {
#[cfg(not(feature = "c003"))]
panic!("tig-runtime was not compiled with '--features c003'");
#[cfg(feature = "c003")]
dispatch_challenge!(c003, cpu)
}
"c004" => {
#[cfg(not(feature = "c004"))]
panic!("tig-runtime was not compiled with '--features c004'");
#[cfg(feature = "c004")]
dispatch_challenge!(c004, gpu)
}
"c005" => {
#[cfg(not(feature = "c005"))]
panic!("tig-runtime was not compiled with '--features c005'");
#[cfg(feature = "c005")]
dispatch_challenge!(c005, gpu)
}
_ => panic!("Unsupported challenge"),
}
};

View File

@ -19,4 +19,14 @@ tig-structs = { path = "../tig-structs" }
tig-utils = { path = "../tig-utils" }
[features]
cuda = ["cudarc", "tig-challenges/cuda"]
cuda = ["cudarc"]
c001 = ["tig-challenges/c001"]
satisfiability = ["c001"]
c002 = ["tig-challenges/c002"]
vehicle_routing = ["c002"]
c003 = ["tig-challenges/c003"]
knapsack = ["c003"]
c004 = ["cuda", "tig-challenges/c004"]
vector_search = ["c004"]
c005 = ["cuda", "tig-challenges/c005"]
hypergraph = ["c005"]

View File

@ -34,7 +34,6 @@ fn cli() -> Command {
)
.arg(
arg!(--gpu [GPU] "Which GPU device to use")
.default_value("0")
.value_parser(clap::value_parser!(usize)),
),
)
@ -59,7 +58,7 @@ fn main() {
*sub_m.get_one::<u64>("NONCE").unwrap(),
sub_m.get_one::<String>("SOLUTION").unwrap().clone(),
sub_m.get_one::<PathBuf>("ptx").cloned(),
sub_m.get_one::<usize>("gpu").unwrap().clone(),
sub_m.get_one::<usize>("gpu").cloned(),
),
Some(("verify_merkle_proof", sub_m)) => verify_merkle_proof(
sub_m.get_one::<String>("ROOT").unwrap().clone(),
@ -78,7 +77,7 @@ pub fn verify_solution(
nonce: u64,
solution_path: String,
ptx_path: Option<PathBuf>,
gpu_device: usize,
gpu_device: Option<usize>,
) -> Result<()> {
let settings = load_settings(&settings);
let solution = load_solution(&solution_path);
@ -86,48 +85,35 @@ pub fn verify_solution(
let mut err_msg = Option::<String>::None;
macro_rules! dispatch_challenges {
( $( ($c:ident, $cpu_or_gpu:tt) ),+ $(,)? ) => {{
match settings.challenge_id.as_str() {
$(
stringify!($c) => {
dispatch_challenges!(@expand $c, $cpu_or_gpu);
}
)+
_ => panic!("Unsupported challenge"),
}
}};
(@expand $c:ident, cpu) => {{
let challenge = $c::Challenge::generate_instance(
&seed,
&settings.difficulty.into(),
).unwrap();
macro_rules! dispatch_challenge {
($c:ident, cpu) => {{
let challenge =
$c::Challenge::generate_instance(&seed, &settings.difficulty.into()).unwrap();
match $c::Solution::try_from(solution) {
Ok(solution) => {
match challenge.verify_solution(&solution) {
Ok(solution) => match challenge.verify_solution(&solution) {
Ok(_) => println!("Solution is valid"),
Err(e) => err_msg = Some(format!("Invalid solution: {}", e)),
}
},
Err(_) => err_msg = Some(format!(
Err(_) => {
err_msg = Some(format!(
"Invalid solution. Cannot convert to {}::Solution",
stringify!($c)
)),
))
}
}
}};
(@expand $c:ident, gpu) => {{
#[cfg(not(feature = "cuda"))]
panic!("tig-runtime was not compiled with '--features cuda'");
#[cfg(feature = "cuda")]
{
($c:ident, gpu) => {{
if ptx_path.is_none() {
panic!("PTX file is required for GPU challenges.");
}
let num_gpus = CudaContext::device_count()?;
if num_gpus == 0 {
panic!("No CUDA devices found");
}
let gpu_device = gpu_device.unwrap_or((nonce % num_gpus as u64) as usize);
let ptx = Ptx::from_file(ptx_path.unwrap());
let ctx = CudaContext::new(gpu_device).unwrap();
ctx.set_blocking_synchronize()?;
@ -141,35 +127,68 @@ pub fn verify_solution(
module.clone(),
stream.clone(),
&prop,
).unwrap();
)
.unwrap();
match $c::Solution::try_from(solution) {
Ok(solution) => {
match challenge.verify_solution(&solution, module.clone(), stream.clone(), &prop) {
match challenge.verify_solution(
&solution,
module.clone(),
stream.clone(),
&prop,
) {
Ok(_) => {
stream.synchronize()?;
ctx.synchronize()?;
println!("Solution is valid");
},
}
Err(e) => err_msg = Some(format!("Invalid solution: {}", e)),
}
},
Err(_) => err_msg = Some(format!(
}
Err(_) => {
err_msg = Some(format!(
"Invalid solution. Cannot convert to {}::Solution",
stringify!($c)
)),
))
}
}
}};
}
dispatch_challenges!(
(c001, cpu),
(c002, cpu),
(c003, cpu),
(c004, gpu),
(c005, gpu)
);
match settings.challenge_id.as_str() {
"c001" => {
#[cfg(not(feature = "c001"))]
panic!("tig-verifier was not compiled with '--features c001'");
#[cfg(feature = "c001")]
dispatch_challenge!(c001, cpu)
}
"c002" => {
#[cfg(not(feature = "c002"))]
panic!("tig-verifier was not compiled with '--features c002'");
#[cfg(feature = "c002")]
dispatch_challenge!(c002, cpu)
}
"c003" => {
#[cfg(not(feature = "c003"))]
panic!("tig-verifier was not compiled with '--features c003'");
#[cfg(feature = "c003")]
dispatch_challenge!(c003, cpu)
}
"c004" => {
#[cfg(not(feature = "c004"))]
panic!("tig-verifier was not compiled with '--features c004'");
#[cfg(feature = "c004")]
dispatch_challenge!(c004, gpu)
}
"c005" => {
#[cfg(not(feature = "c005"))]
panic!("tig-verifier was not compiled with '--features c005'");
#[cfg(feature = "c005")]
dispatch_challenge!(c005, gpu)
}
_ => panic!("Unsupported challenge"),
}
if let Some(err_msg) = err_msg {
eprintln!("Verification error: {}", err_msg);