mirror of
https://github.com/tig-pool-nk/tig-monorepo.git
synced 2026-02-21 15:47:24 +08:00
Rework architecture so each challenge has separate runtime & docker.
This commit is contained in:
parent
7ebad69cf7
commit
89d86f9deb
@ -1,8 +1,13 @@
|
|||||||
ARG BASE_IMAGE=ubuntu:24.04
|
ARG BASE_IMAGE=ubuntu:24.04
|
||||||
|
ARG CHALLENGE
|
||||||
|
|
||||||
# Development environment stage
|
# Development environment stage
|
||||||
FROM ${BASE_IMAGE}
|
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) && \
|
RUN ARCH=$(uname -m) && \
|
||||||
if [ "$ARCH" != "aarch64" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "amd64" ] && [ "$ARCH" != "x86_64" ]; then \
|
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; \
|
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 component add rust-src && \
|
||||||
rustup target add $RUST_TARGET && \
|
rustup target add $RUST_TARGET && \
|
||||||
RUST_LIBDIR=$(rustc --print target-libdir --target=$RUST_TARGET) && \
|
RUST_LIBDIR=$(rustc --print target-libdir --target=$RUST_TARGET) && \
|
||||||
ln -s $RUST_LIBDIR /usr/local/lib/rust && \
|
ln -s $RUST_LIBDIR /usr/local/lib/rust
|
||||||
echo "export LD_LIBRARY_PATH=\"${LD_LIBRARY_PATH}:/usr/local/lib/rust\"" >> /etc/bash.bashrc && \
|
ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/lib/rust"
|
||||||
echo "export RUST_TARGET=\"${RUST_TARGET}\"" >> /etc/bash.bashrc
|
|
||||||
|
|
||||||
RUN ARCH=$(uname -m) && \
|
RUN ARCH=$(uname -m) && \
|
||||||
LLVM_URL=$(if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then \
|
LLVM_URL=$(if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then \
|
||||||
@ -42,25 +46,20 @@ RUN ARCH=$(uname -m) && \
|
|||||||
rm -rf llvm.tar.zst && \
|
rm -rf llvm.tar.zst && \
|
||||||
ln -s /opt/llvm/bin/* /usr/local/bin/
|
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
|
COPY . /tmp/tig-monorepo
|
||||||
WORKDIR /tmp/tig-monorepo
|
WORKDIR /tmp/tig-monorepo
|
||||||
|
|
||||||
RUN if command -v nvcc > /dev/null 2>&1; then \
|
RUN cargo build -r -p tig-runtime --features $CHALLENGE && \
|
||||||
cargo build -r -p tig-runtime --features cuda && \
|
cargo build -r -p tig-verifier --features $CHALLENGE && \
|
||||||
cargo build -r -p tig-verifier --features cuda; \
|
|
||||||
else \
|
|
||||||
cargo build -r -p tig-runtime && \
|
|
||||||
cargo build -r -p tig-verifier; \
|
|
||||||
fi && \
|
|
||||||
mv target/release/tig-runtime /usr/local/bin/ && \
|
mv target/release/tig-runtime /usr/local/bin/ && \
|
||||||
mv target/release/tig-verifier /usr/local/bin/ && \
|
mv target/release/tig-verifier /usr/local/bin/ && \
|
||||||
chmod +x /usr/local/bin/tig-runtime && \
|
chmod +x /usr/local/bin/tig-runtime && \
|
||||||
chmod +x /usr/local/bin/tig-verifier && \
|
chmod +x /usr/local/bin/tig-verifier && \
|
||||||
rm -rf tig-monorepo
|
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
|
WORKDIR /app
|
||||||
|
|||||||
@ -1,27 +1,28 @@
|
|||||||
ARG BASE_IMAGE=ubuntu:24.04
|
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}
|
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
|
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-runtime /usr/local/bin/tig-runtime
|
||||||
COPY --from=dev /usr/local/bin/tig-verifier /usr/local/bin/tig-verifier
|
COPY --from=dev /usr/local/bin/tig-verifier /usr/local/bin/tig-verifier
|
||||||
COPY --from=dev /usr/local/lib/rust /usr/local/lib/rust
|
COPY --from=dev /usr/local/lib/rust /usr/local/lib/rust
|
||||||
|
|
||||||
RUN chmod +x /usr/local/bin/tig-runtime && \
|
RUN chmod +x /usr/local/bin/tig-runtime && \
|
||||||
chmod +x /usr/local/bin/tig-verifier && \
|
chmod +x /usr/local/bin/tig-verifier
|
||||||
echo "export LD_LIBRARY_PATH=\"${LD_LIBRARY_PATH}:/usr/local/lib/rust\"" >> /etc/bash.bashrc
|
ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/lib/rust"
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@ -7,9 +7,13 @@ import requests
|
|||||||
import sys
|
import sys
|
||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
|
CHALLENGE = os.getenv("CHALLENGE")
|
||||||
|
if CHALLENGE is None:
|
||||||
|
print("CHALLENGE environment variable must be set!")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description='TIG Algorithm Downloader')
|
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('algorithm', help="Algorithm name or id")
|
||||||
parser.add_argument('--out', default="tig-algorithms/lib", help="Output directory (default: tig-algorithms/lib)")
|
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")
|
parser.add_argument('--testnet', action='store_true', help="Use testnet API")
|
||||||
@ -26,12 +30,12 @@ def main():
|
|||||||
c_id = next(
|
c_id = next(
|
||||||
(
|
(
|
||||||
c['id'] for c in challenges
|
c['id'] for c in challenges
|
||||||
if c['details']['name'] == args.challenge or c['id'] == args.challenge
|
if c['details']['name'] == CHALLENGE
|
||||||
),
|
),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
if c_id is None:
|
if c_id is None:
|
||||||
print(f"Challenge '{args.challenge}' not found.")
|
print(f"Challenge '{CHALLENGE}' not found.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
a_id = next(
|
a_id = next(
|
||||||
@ -44,7 +48,7 @@ def main():
|
|||||||
None
|
None
|
||||||
)
|
)
|
||||||
if a_id is 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)
|
sys.exit(1)
|
||||||
|
|
||||||
download_url = download_urls.get(a_id)
|
download_url = download_urls.get(a_id)
|
||||||
@ -54,7 +58,7 @@ def main():
|
|||||||
|
|
||||||
print(f"Downloading algorithm '{args.algorithm}' from {download_url}...")
|
print(f"Downloading algorithm '{args.algorithm}' from {download_url}...")
|
||||||
resp = requests.get(download_url, stream=True)
|
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)
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
with tarfile.open(fileobj=io.BytesIO(resp.content), mode='r:gz') as tar:
|
with tarfile.open(fileobj=io.BytesIO(resp.content), mode='r:gz') as tar:
|
||||||
tar.extractall(path=output_dir)
|
tar.extractall(path=output_dir)
|
||||||
|
|||||||
@ -1,15 +1,17 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import io
|
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
import sys
|
import sys
|
||||||
import tarfile
|
|
||||||
|
CHALLENGE = os.getenv("CHALLENGE")
|
||||||
|
if CHALLENGE is None:
|
||||||
|
print("CHALLENGE environment variable must be set!")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description='TIG Algorithm Lister')
|
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")
|
parser.add_argument('--testnet', action='store_true', help="Use testnet API")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
@ -24,12 +26,12 @@ def main():
|
|||||||
c_id = next(
|
c_id = next(
|
||||||
(
|
(
|
||||||
c['id'] for c in challenges
|
c['id'] for c in challenges
|
||||||
if c['details']['name'] == args.challenge or c['id'] == args.challenge
|
if c['details']['name'] == CHALLENGE
|
||||||
),
|
),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
if c_id is None:
|
if c_id is None:
|
||||||
print(f"Challenge '{args.challenge}' not found.")
|
print(f"Challenge '{CHALLENGE}' not found.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
algorithms = sorted([
|
algorithms = sorted([
|
||||||
|
|||||||
@ -37,6 +37,11 @@ elif (VISIBLE_GPUS := os.environ.get("CUDA_VISIBLE_DEVICES", None)) is None:
|
|||||||
else:
|
else:
|
||||||
VISIBLE_GPUS = list(map(int, VISIBLE_GPUS.split(",")))
|
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():
|
def now():
|
||||||
return int(time.time() * 1000)
|
return int(time.time() * 1000)
|
||||||
|
|
||||||
@ -44,7 +49,6 @@ def now():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
tig_runtime_path = shutil.which("tig-runtime")
|
tig_runtime_path = shutil.which("tig-runtime")
|
||||||
parser = argparse.ArgumentParser(description="TIG Algorithm Tester")
|
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("algorithm", type=str, help="Algorithm name")
|
||||||
parser.add_argument("difficulty", type=str, help="JSON string of difficulty")
|
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})")
|
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()
|
args = parser.parse_args()
|
||||||
|
|
||||||
so_path = f"{args.lib_dir}/{args.challenge}/{CPU_ARCH}/{args.algorithm}.so"
|
so_path = f"{args.lib_dir}/{CHALLENGE}/{CPU_ARCH}/{args.algorithm}.so"
|
||||||
ptx_path = f"{args.lib_dir}/{args.challenge}/ptx/{args.algorithm}.ptx"
|
ptx_path = f"{args.lib_dir}/{CHALLENGE}/ptx/{args.algorithm}.ptx"
|
||||||
|
|
||||||
if not os.path.exists(so_path):
|
if not os.path.exists(so_path):
|
||||||
print(
|
print(
|
||||||
@ -93,10 +97,7 @@ f"""Library not found at {so_path}:
|
|||||||
"hypergraph": "c005",
|
"hypergraph": "c005",
|
||||||
"optimiser": "c006",
|
"optimiser": "c006",
|
||||||
}
|
}
|
||||||
challenge_id = challenge_ids.get(args.challenge, None)
|
challenge_id = challenge_ids[CHALLENGE]
|
||||||
if challenge_id is None:
|
|
||||||
print(f"Unknown challenge '{args.challenge}'. Choices: ({', '.join(challenge_ids.keys())})")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
settings = {"algorithm_id": "", "challenge_id": challenge_id, "difficulty": difficulty, "block_id": "", "player_id": ""}
|
settings = {"algorithm_id": "", "challenge_id": challenge_id, "difficulty": difficulty, "block_id": "", "player_id": ""}
|
||||||
pool = ThreadPoolExecutor(max_workers=args.workers + 1)
|
pool = ThreadPoolExecutor(max_workers=args.workers + 1)
|
||||||
|
|||||||
@ -23,4 +23,14 @@ tig-challenges = { path = "../tig-challenges" }
|
|||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[features]
|
[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"]
|
||||||
|
|||||||
@ -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 const BUILD_TIME_PATH: &str = env!("CARGO_MANIFEST_DIR");
|
||||||
|
|
||||||
pub mod knapsack;
|
#[cfg(feature = "c001")]
|
||||||
pub use knapsack as c003;
|
|
||||||
pub mod satisfiability;
|
pub mod satisfiability;
|
||||||
|
#[cfg(feature = "c001")]
|
||||||
pub use satisfiability as c001;
|
pub use satisfiability as c001;
|
||||||
|
#[cfg(feature = "c002")]
|
||||||
pub mod vehicle_routing;
|
pub mod vehicle_routing;
|
||||||
|
#[cfg(feature = "c002")]
|
||||||
pub use vehicle_routing as c002;
|
pub use vehicle_routing as c002;
|
||||||
|
#[cfg(feature = "c003")]
|
||||||
#[cfg(feature = "cuda")]
|
pub mod knapsack;
|
||||||
|
#[cfg(feature = "c003")]
|
||||||
|
pub use knapsack as c003;
|
||||||
|
#[cfg(feature = "c004")]
|
||||||
pub mod vector_search;
|
pub mod vector_search;
|
||||||
#[cfg(feature = "cuda")]
|
#[cfg(feature = "c004")]
|
||||||
pub use vector_search as c004;
|
pub use vector_search as c004;
|
||||||
#[cfg(feature = "cuda")]
|
#[cfg(feature = "c005")]
|
||||||
pub mod hypergraph;
|
pub mod hypergraph;
|
||||||
#[cfg(feature = "cuda")]
|
#[cfg(feature = "c005")]
|
||||||
pub use hypergraph as c005;
|
pub use hypergraph as c005;
|
||||||
|
|||||||
@ -19,4 +19,14 @@ tig-algorithms = { path = "../tig-algorithms" }
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
entry_point = []
|
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"]
|
||||||
|
|||||||
48
tig-binary/scripts/build_algorithm
Normal file
48
tig-binary/scripts/build_algorithm
Normal 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
|
||||||
@ -3,11 +3,15 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
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
|
# Import the dictionary from ptx_instructions.py
|
||||||
instruction_fuel_cost = {
|
instruction_fuel_cost = {
|
||||||
'add.u32': 2,
|
'add.u32': 2,
|
||||||
@ -232,12 +236,11 @@ $NORMAL_EXIT:
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description='Compile PTX with injected runtime signature')
|
parser = argparse.ArgumentParser(description='Compile PTX with injected runtime signature')
|
||||||
parser.add_argument('challenge', help='Challenge name')
|
|
||||||
parser.add_argument('algorithm', help='Algorithm name')
|
parser.add_argument('algorithm', help='Algorithm name')
|
||||||
|
|
||||||
args = parser.parse_args()
|
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"
|
framework_cu = "tig-binary/src/framework.cu"
|
||||||
if not os.path.exists(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"
|
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):
|
if not os.path.exists(challenge_cu):
|
||||||
raise FileNotFoundError(
|
raise FileNotFoundError(
|
||||||
f"Challenge code does not exist @ '{challenge_cu}'. Is the challenge name correct?"
|
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_cu = f"tig-algorithms/src/{CHALLENGE}/{args.algorithm}.cu"
|
||||||
algorithm_cu2 = f"tig-algorithms/src/{args.challenge}/{args.algorithm}/benchmarker_outbound.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):
|
if not os.path.exists(algorithm_cu) and not os.path.exists(algorithm_cu2):
|
||||||
raise FileNotFoundError(
|
raise FileNotFoundError(
|
||||||
f"Algorithm code does not exist @ '{algorithm_cu}' or '{algorithm_cu2}'. Is the algorithm name correct?"
|
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)
|
parsed = parse_ptx_code(ptx_code)
|
||||||
modified_code = inject_fuel_and_runtime_sig(parsed, kernels_to_ignore)
|
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)
|
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:
|
with open(output_path, 'w') as f:
|
||||||
f.writelines(modified_code)
|
f.writelines(modified_code)
|
||||||
print(f"Wrote ptx to {output_path}")
|
print(f"Wrote ptx to {output_path}")
|
||||||
|
|||||||
@ -2,55 +2,34 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
CUDA=false
|
# Check if CHALLENGE environment variable is set
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
if [ -z "$CHALLENGE" ]; then
|
if [ -z "$CHALLENGE" ]; then
|
||||||
echo "Error: CHALLENGE argument is empty"
|
echo "Error: CHALLENGE environment variable is not set."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$ALGORITHM" ]; then
|
# Check if ALGORITHM argument is provided
|
||||||
echo "Error: ALGORITHM argument is empty"
|
if [ -z "$1" ]; then
|
||||||
exit 1
|
echo "Error: ALGORITHM argument is required."
|
||||||
|
echo "Usage: $0 <ALGORITHM>"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
ALGORITHM="$1"
|
||||||
|
|
||||||
echo "Compiling .so for $CHALLENGE/$ALGORITHM"
|
echo "Compiling .so for $CHALLENGE/$ALGORITHM"
|
||||||
cp tig-binary/src/entry_point_template.rs tig-binary/src/entry_point.rs
|
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/{CHALLENGE}/$CHALLENGE/g" tig-binary/src/entry_point.rs
|
||||||
sed -i "s/{ALGORITHM}/$ALGORITHM/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 $CHALLENGE"
|
||||||
FEATURES="entry_point cuda"
|
|
||||||
else
|
|
||||||
FEATURES="entry_point"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
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" \
|
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 \
|
cargo +nightly-2025-02-10 build \
|
||||||
-p tig-binary \
|
-p tig-binary \
|
||||||
|
|||||||
@ -23,3 +23,13 @@ statrs = { version = "0.18.0" }
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
cuda = ["cudarc"]
|
cuda = ["cudarc"]
|
||||||
|
c001 = []
|
||||||
|
satisfiability = ["c001"]
|
||||||
|
c002 = []
|
||||||
|
vehicle_routing = ["c002"]
|
||||||
|
c003 = []
|
||||||
|
knapsack = ["c003"]
|
||||||
|
c004 = ["cuda"]
|
||||||
|
vector_search = ["c004"]
|
||||||
|
c005 = ["cuda"]
|
||||||
|
hypergraph = ["c005"]
|
||||||
|
|||||||
@ -1,17 +1,22 @@
|
|||||||
pub const BUILD_TIME_PATH: &str = env!("CARGO_MANIFEST_DIR");
|
pub const BUILD_TIME_PATH: &str = env!("CARGO_MANIFEST_DIR");
|
||||||
|
|
||||||
pub mod knapsack;
|
#[cfg(feature = "c001")]
|
||||||
pub use knapsack as c003;
|
|
||||||
pub mod satisfiability;
|
pub mod satisfiability;
|
||||||
|
#[cfg(feature = "c001")]
|
||||||
pub use satisfiability as c001;
|
pub use satisfiability as c001;
|
||||||
|
#[cfg(feature = "c002")]
|
||||||
pub mod vehicle_routing;
|
pub mod vehicle_routing;
|
||||||
|
#[cfg(feature = "c002")]
|
||||||
pub use vehicle_routing as c002;
|
pub use vehicle_routing as c002;
|
||||||
|
#[cfg(feature = "c003")]
|
||||||
#[cfg(feature = "cuda")]
|
pub mod knapsack;
|
||||||
|
#[cfg(feature = "c003")]
|
||||||
|
pub use knapsack as c003;
|
||||||
|
#[cfg(feature = "c004")]
|
||||||
pub mod vector_search;
|
pub mod vector_search;
|
||||||
#[cfg(feature = "cuda")]
|
#[cfg(feature = "c004")]
|
||||||
pub use vector_search as c004;
|
pub use vector_search as c004;
|
||||||
#[cfg(feature = "cuda")]
|
#[cfg(feature = "c005")]
|
||||||
pub mod hypergraph;
|
pub mod hypergraph;
|
||||||
#[cfg(feature = "cuda")]
|
#[cfg(feature = "c005")]
|
||||||
pub use hypergraph as c005;
|
pub use hypergraph as c005;
|
||||||
|
|||||||
@ -21,4 +21,14 @@ tig-structs = { path = "../tig-structs" }
|
|||||||
tig-utils = { path = "../tig-utils" }
|
tig-utils = { path = "../tig-utils" }
|
||||||
|
|
||||||
[features]
|
[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"]
|
||||||
|
|||||||
@ -51,7 +51,6 @@ fn cli() -> Command {
|
|||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
arg!(--gpu [GPU] "Which GPU device to use")
|
arg!(--gpu [GPU] "Which GPU device to use")
|
||||||
.default_value("0")
|
|
||||||
.value_parser(clap::value_parser!(usize)),
|
.value_parser(clap::value_parser!(usize)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -68,7 +67,7 @@ fn main() {
|
|||||||
*matches.get_one::<u64>("fuel").unwrap(),
|
*matches.get_one::<u64>("fuel").unwrap(),
|
||||||
matches.get_one::<PathBuf>("output").cloned(),
|
matches.get_one::<PathBuf>("output").cloned(),
|
||||||
matches.get_one::<bool>("compress").unwrap().clone(),
|
matches.get_one::<bool>("compress").unwrap().clone(),
|
||||||
matches.get_one::<usize>("gpu").unwrap().clone(),
|
matches.get_one::<usize>("gpu").cloned(),
|
||||||
) {
|
) {
|
||||||
eprintln!("Error: {}", e);
|
eprintln!("Error: {}", e);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
@ -80,13 +79,11 @@ pub fn compute_solution(
|
|||||||
rand_hash: String,
|
rand_hash: String,
|
||||||
nonce: u64,
|
nonce: u64,
|
||||||
library_path: PathBuf,
|
library_path: PathBuf,
|
||||||
#[cfg(feature = "cuda")] ptx_path: Option<PathBuf>,
|
ptx_path: Option<PathBuf>,
|
||||||
#[cfg(not(feature = "cuda"))] _ptx_path: Option<PathBuf>,
|
|
||||||
max_fuel: u64,
|
max_fuel: u64,
|
||||||
output_file: Option<PathBuf>,
|
output_file: Option<PathBuf>,
|
||||||
compress: bool,
|
compress: bool,
|
||||||
#[cfg(feature = "cuda")] gpu_device: usize,
|
gpu_device: Option<usize>,
|
||||||
#[cfg(not(feature = "cuda"))] _gpu_device: usize,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let settings = load_settings(&settings);
|
let settings = load_settings(&settings);
|
||||||
let seed = settings.calc_seed(&rand_hash, nonce);
|
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")? };
|
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()) };
|
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 {
|
macro_rules! dispatch_challenge {
|
||||||
($c:ident, cpu) => {{
|
($c:ident, cpu) => {{
|
||||||
// library function may exit 87 if it runs out of fuel
|
// library function may exit 87 if it runs out of fuel
|
||||||
@ -138,141 +140,157 @@ pub fn compute_solution(
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
($c:ident, gpu) => {{
|
($c:ident, gpu) => {{
|
||||||
#[cfg(not(feature = "cuda"))]
|
if ptx_path.is_none() {
|
||||||
panic!("tig-runtime was not compiled with '--features cuda'");
|
panic!("PTX file is required for GPU challenges.");
|
||||||
|
|
||||||
#[cfg(feature = "cuda")]
|
|
||||||
{
|
|
||||||
if ptx_path.is_none() {
|
|
||||||
panic!("PTX file is required for GPU challenges.");
|
|
||||||
}
|
|
||||||
let ptx_path = ptx_path.unwrap();
|
|
||||||
// library function may exit 87 if it runs out of fuel
|
|
||||||
let solve_challenge_fn = unsafe {
|
|
||||||
library.get::<fn(
|
|
||||||
&$c::Challenge,
|
|
||||||
Arc<CudaModule>,
|
|
||||||
Arc<CudaStream>,
|
|
||||||
&cudaDeviceProp,
|
|
||||||
) -> Result<Option<$c::Solution>, String>>(
|
|
||||||
b"entry_point"
|
|
||||||
)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let gpu_fuel_scale = 20; // scale fuel to loosely align with CPU
|
|
||||||
let ptx_content = std::fs::read_to_string(&ptx_path)
|
|
||||||
.map_err(|e| anyhow!("Failed to read PTX file: {}", e))?;
|
|
||||||
let max_fuel_hex = format!("0x{:016x}", max_fuel * gpu_fuel_scale);
|
|
||||||
let modified_ptx = ptx_content.replace("0xdeadbeefdeadbeef", &max_fuel_hex);
|
|
||||||
|
|
||||||
let ptx = Ptx::from_src(modified_ptx);
|
|
||||||
let ctx = CudaContext::new(gpu_device)?;
|
|
||||||
ctx.set_blocking_synchronize()?;
|
|
||||||
let module = ctx.load_module(ptx)?;
|
|
||||||
let stream = ctx.fuel_check_stream();
|
|
||||||
let prop = get_device_prop(gpu_device as i32)?;
|
|
||||||
|
|
||||||
let challenge = $c::Challenge::generate_instance(
|
|
||||||
&seed,
|
|
||||||
&settings.difficulty.into(),
|
|
||||||
module.clone(),
|
|
||||||
stream.clone(),
|
|
||||||
&prop,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let initialize_kernel = module.load_function("initialize_kernel")?;
|
|
||||||
|
|
||||||
let cfg = LaunchConfig {
|
|
||||||
grid_dim: (1, 1, 1),
|
|
||||||
block_dim: (1, 1, 1),
|
|
||||||
shared_mem_bytes: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
stream
|
|
||||||
.launch_builder(&initialize_kernel)
|
|
||||||
.arg(&(u64::from_be_bytes(seed[8..16].try_into().unwrap())))
|
|
||||||
.launch(cfg)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
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"))
|
|
||||||
{
|
|
||||||
break 'out_of_fuel (max_fuel + 1, 0, Solution::new(), None);
|
|
||||||
}
|
|
||||||
let result = result.map_err(|e| anyhow!("{}", e))?;
|
|
||||||
stream.synchronize()?;
|
|
||||||
ctx.synchronize()?;
|
|
||||||
|
|
||||||
let mut fuel_usage = stream.alloc_zeros::<u64>(1)?;
|
|
||||||
let mut signature = stream.alloc_zeros::<u64>(1)?;
|
|
||||||
let mut error_stat = stream.alloc_zeros::<u64>(1)?;
|
|
||||||
|
|
||||||
let finalize_kernel = module.load_function("finalize_kernel")?;
|
|
||||||
|
|
||||||
let cfg = LaunchConfig {
|
|
||||||
grid_dim: (1, 1, 1),
|
|
||||||
block_dim: (1, 1, 1),
|
|
||||||
shared_mem_bytes: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
stream
|
|
||||||
.launch_builder(&finalize_kernel)
|
|
||||||
.arg(&mut fuel_usage)
|
|
||||||
.arg(&mut signature)
|
|
||||||
.arg(&mut error_stat)
|
|
||||||
.launch(cfg)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if stream.memcpy_dtov(&error_stat)?[0] != 0 {
|
|
||||||
break 'out_of_fuel (max_fuel + 1, 0, Solution::new(), None);
|
|
||||||
}
|
|
||||||
let fuel_consumed = (stream.memcpy_dtov(&fuel_usage)?[0] / gpu_fuel_scale
|
|
||||||
+ max_fuel
|
|
||||||
- unsafe { **library.get::<*const u64>(b"__fuel_remaining")? });
|
|
||||||
|
|
||||||
if fuel_consumed > max_fuel {
|
|
||||||
break 'out_of_fuel (max_fuel + 1, 0, Solution::new(), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
let runtime_signature = (stream.memcpy_dtov(&signature)?[0]
|
|
||||||
^ unsafe { **library.get::<*const u64>(b"__runtime_signature")? });
|
|
||||||
|
|
||||||
let (solution, invalid_reason) = match result {
|
|
||||||
Some(s) => (
|
|
||||||
serde_json::to_value(&s)
|
|
||||||
.unwrap()
|
|
||||||
.as_object()
|
|
||||||
.unwrap()
|
|
||||||
.to_owned(),
|
|
||||||
match challenge.verify_solution(
|
|
||||||
&s,
|
|
||||||
module.clone(),
|
|
||||||
stream.clone(),
|
|
||||||
&prop,
|
|
||||||
) {
|
|
||||||
Ok(_) => None,
|
|
||||||
Err(e) => Some(e.to_string()),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
None => (Solution::new(), None),
|
|
||||||
};
|
|
||||||
|
|
||||||
(fuel_consumed, runtime_signature, solution, invalid_reason)
|
|
||||||
}
|
}
|
||||||
|
let ptx_path = ptx_path.unwrap();
|
||||||
|
// library function may exit 87 if it runs out of fuel
|
||||||
|
let solve_challenge_fn = unsafe {
|
||||||
|
library.get::<fn(
|
||||||
|
&$c::Challenge,
|
||||||
|
Arc<CudaModule>,
|
||||||
|
Arc<CudaStream>,
|
||||||
|
&cudaDeviceProp,
|
||||||
|
) -> Result<Option<$c::Solution>, String>>(b"entry_point")?
|
||||||
|
};
|
||||||
|
|
||||||
|
let gpu_fuel_scale = 20; // scale fuel to loosely align with CPU
|
||||||
|
let ptx_content = std::fs::read_to_string(&ptx_path)
|
||||||
|
.map_err(|e| anyhow!("Failed to read PTX file: {}", e))?;
|
||||||
|
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()?;
|
||||||
|
let module = ctx.load_module(ptx)?;
|
||||||
|
let stream = ctx.fuel_check_stream();
|
||||||
|
let prop = get_device_prop(gpu_device as i32)?;
|
||||||
|
|
||||||
|
let challenge = $c::Challenge::generate_instance(
|
||||||
|
&seed,
|
||||||
|
&settings.difficulty.into(),
|
||||||
|
module.clone(),
|
||||||
|
stream.clone(),
|
||||||
|
&prop,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let initialize_kernel = module.load_function("initialize_kernel")?;
|
||||||
|
|
||||||
|
let cfg = LaunchConfig {
|
||||||
|
grid_dim: (1, 1, 1),
|
||||||
|
block_dim: (1, 1, 1),
|
||||||
|
shared_mem_bytes: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
stream
|
||||||
|
.launch_builder(&initialize_kernel)
|
||||||
|
.arg(&(u64::from_be_bytes(seed[8..16].try_into().unwrap())))
|
||||||
|
.launch(cfg)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
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"))
|
||||||
|
{
|
||||||
|
break 'out_of_fuel (max_fuel + 1, 0, Solution::new(), None);
|
||||||
|
}
|
||||||
|
let result = result.map_err(|e| anyhow!("{}", e))?;
|
||||||
|
stream.synchronize()?;
|
||||||
|
ctx.synchronize()?;
|
||||||
|
|
||||||
|
let mut fuel_usage = stream.alloc_zeros::<u64>(1)?;
|
||||||
|
let mut signature = stream.alloc_zeros::<u64>(1)?;
|
||||||
|
let mut error_stat = stream.alloc_zeros::<u64>(1)?;
|
||||||
|
|
||||||
|
let finalize_kernel = module.load_function("finalize_kernel")?;
|
||||||
|
|
||||||
|
let cfg = LaunchConfig {
|
||||||
|
grid_dim: (1, 1, 1),
|
||||||
|
block_dim: (1, 1, 1),
|
||||||
|
shared_mem_bytes: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
stream
|
||||||
|
.launch_builder(&finalize_kernel)
|
||||||
|
.arg(&mut fuel_usage)
|
||||||
|
.arg(&mut signature)
|
||||||
|
.arg(&mut error_stat)
|
||||||
|
.launch(cfg)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if stream.memcpy_dtov(&error_stat)?[0] != 0 {
|
||||||
|
break 'out_of_fuel (max_fuel + 1, 0, Solution::new(), None);
|
||||||
|
}
|
||||||
|
let fuel_consumed = (stream.memcpy_dtov(&fuel_usage)?[0] / gpu_fuel_scale
|
||||||
|
+ max_fuel
|
||||||
|
- unsafe { **library.get::<*const u64>(b"__fuel_remaining")? });
|
||||||
|
|
||||||
|
if fuel_consumed > max_fuel {
|
||||||
|
break 'out_of_fuel (max_fuel + 1, 0, Solution::new(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let runtime_signature = (stream.memcpy_dtov(&signature)?[0]
|
||||||
|
^ unsafe { **library.get::<*const u64>(b"__runtime_signature")? });
|
||||||
|
|
||||||
|
let (solution, invalid_reason) = match result {
|
||||||
|
Some(s) => (
|
||||||
|
serde_json::to_value(&s)
|
||||||
|
.unwrap()
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.to_owned(),
|
||||||
|
match challenge.verify_solution(&s, module.clone(), stream.clone(), &prop) {
|
||||||
|
Ok(_) => None,
|
||||||
|
Err(e) => Some(e.to_string()),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
None => (Solution::new(), None),
|
||||||
|
};
|
||||||
|
|
||||||
|
(fuel_consumed, runtime_signature, solution, invalid_reason)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
match settings.challenge_id.as_str() {
|
match settings.challenge_id.as_str() {
|
||||||
"c001" => dispatch_challenge!(c001, cpu),
|
"c001" => {
|
||||||
"c002" => dispatch_challenge!(c002, cpu),
|
#[cfg(not(feature = "c001"))]
|
||||||
"c003" => dispatch_challenge!(c003, cpu),
|
panic!("tig-runtime was not compiled with '--features c001'");
|
||||||
"c004" => dispatch_challenge!(c004, gpu),
|
#[cfg(feature = "c001")]
|
||||||
"c005" => dispatch_challenge!(c005, gpu),
|
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"),
|
_ => panic!("Unsupported challenge"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -19,4 +19,14 @@ tig-structs = { path = "../tig-structs" }
|
|||||||
tig-utils = { path = "../tig-utils" }
|
tig-utils = { path = "../tig-utils" }
|
||||||
|
|
||||||
[features]
|
[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"]
|
||||||
|
|||||||
@ -34,7 +34,6 @@ fn cli() -> Command {
|
|||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
arg!(--gpu [GPU] "Which GPU device to use")
|
arg!(--gpu [GPU] "Which GPU device to use")
|
||||||
.default_value("0")
|
|
||||||
.value_parser(clap::value_parser!(usize)),
|
.value_parser(clap::value_parser!(usize)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -59,7 +58,7 @@ fn main() {
|
|||||||
*sub_m.get_one::<u64>("NONCE").unwrap(),
|
*sub_m.get_one::<u64>("NONCE").unwrap(),
|
||||||
sub_m.get_one::<String>("SOLUTION").unwrap().clone(),
|
sub_m.get_one::<String>("SOLUTION").unwrap().clone(),
|
||||||
sub_m.get_one::<PathBuf>("ptx").cloned(),
|
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(
|
Some(("verify_merkle_proof", sub_m)) => verify_merkle_proof(
|
||||||
sub_m.get_one::<String>("ROOT").unwrap().clone(),
|
sub_m.get_one::<String>("ROOT").unwrap().clone(),
|
||||||
@ -78,7 +77,7 @@ pub fn verify_solution(
|
|||||||
nonce: u64,
|
nonce: u64,
|
||||||
solution_path: String,
|
solution_path: String,
|
||||||
ptx_path: Option<PathBuf>,
|
ptx_path: Option<PathBuf>,
|
||||||
gpu_device: usize,
|
gpu_device: Option<usize>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let settings = load_settings(&settings);
|
let settings = load_settings(&settings);
|
||||||
let solution = load_solution(&solution_path);
|
let solution = load_solution(&solution_path);
|
||||||
@ -86,90 +85,110 @@ pub fn verify_solution(
|
|||||||
|
|
||||||
let mut err_msg = Option::<String>::None;
|
let mut err_msg = Option::<String>::None;
|
||||||
|
|
||||||
macro_rules! dispatch_challenges {
|
macro_rules! dispatch_challenge {
|
||||||
( $( ($c:ident, $cpu_or_gpu:tt) ),+ $(,)? ) => {{
|
($c:ident, cpu) => {{
|
||||||
match settings.challenge_id.as_str() {
|
let challenge =
|
||||||
$(
|
$c::Challenge::generate_instance(&seed, &settings.difficulty.into()).unwrap();
|
||||||
stringify!($c) => {
|
|
||||||
dispatch_challenges!(@expand $c, $cpu_or_gpu);
|
match $c::Solution::try_from(solution) {
|
||||||
}
|
Ok(solution) => match challenge.verify_solution(&solution) {
|
||||||
)+
|
Ok(_) => println!("Solution is valid"),
|
||||||
_ => panic!("Unsupported challenge"),
|
Err(e) => err_msg = Some(format!("Invalid solution: {}", e)),
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
err_msg = Some(format!(
|
||||||
|
"Invalid solution. Cannot convert to {}::Solution",
|
||||||
|
stringify!($c)
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
(@expand $c:ident, cpu) => {{
|
($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()?;
|
||||||
|
let module = ctx.load_module(ptx).unwrap();
|
||||||
|
let stream = ctx.default_stream();
|
||||||
|
let prop = get_device_prop(gpu_device as i32).unwrap();
|
||||||
|
|
||||||
let challenge = $c::Challenge::generate_instance(
|
let challenge = $c::Challenge::generate_instance(
|
||||||
&seed,
|
&seed,
|
||||||
&settings.difficulty.into(),
|
&settings.difficulty.into(),
|
||||||
).unwrap();
|
module.clone(),
|
||||||
|
stream.clone(),
|
||||||
|
&prop,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
match $c::Solution::try_from(solution) {
|
match $c::Solution::try_from(solution) {
|
||||||
Ok(solution) => {
|
Ok(solution) => {
|
||||||
match challenge.verify_solution(&solution) {
|
match challenge.verify_solution(
|
||||||
Ok(_) => println!("Solution is valid"),
|
&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(e) => err_msg = Some(format!("Invalid solution: {}", e)),
|
||||||
}
|
}
|
||||||
},
|
|
||||||
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")]
|
|
||||||
{
|
|
||||||
if ptx_path.is_none() {
|
|
||||||
panic!("PTX file is required for GPU challenges.");
|
|
||||||
}
|
}
|
||||||
|
Err(_) => {
|
||||||
let ptx = Ptx::from_file(ptx_path.unwrap());
|
err_msg = Some(format!(
|
||||||
let ctx = CudaContext::new(gpu_device).unwrap();
|
|
||||||
ctx.set_blocking_synchronize()?;
|
|
||||||
let module = ctx.load_module(ptx).unwrap();
|
|
||||||
let stream = ctx.default_stream();
|
|
||||||
let prop = get_device_prop(gpu_device as i32).unwrap();
|
|
||||||
|
|
||||||
let challenge = $c::Challenge::generate_instance(
|
|
||||||
&seed,
|
|
||||||
&settings.difficulty.into(),
|
|
||||||
module.clone(),
|
|
||||||
stream.clone(),
|
|
||||||
&prop,
|
|
||||||
).unwrap();
|
|
||||||
|
|
||||||
match $c::Solution::try_from(solution) {
|
|
||||||
Ok(solution) => {
|
|
||||||
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!(
|
|
||||||
"Invalid solution. Cannot convert to {}::Solution",
|
"Invalid solution. Cannot convert to {}::Solution",
|
||||||
stringify!($c)
|
stringify!($c)
|
||||||
)),
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_challenges!(
|
match settings.challenge_id.as_str() {
|
||||||
(c001, cpu),
|
"c001" => {
|
||||||
(c002, cpu),
|
#[cfg(not(feature = "c001"))]
|
||||||
(c003, cpu),
|
panic!("tig-verifier was not compiled with '--features c001'");
|
||||||
(c004, gpu),
|
#[cfg(feature = "c001")]
|
||||||
(c005, gpu)
|
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 {
|
if let Some(err_msg) = err_msg {
|
||||||
eprintln!("Verification error: {}", err_msg);
|
eprintln!("Verification error: {}", err_msg);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user