Join the distributed search for square-cube pandigitals!
Square-cube pandigials ("nice" numbers) seem to be distributed pseudo-randomly. It doesn't take very long to check if a number is pandigital in a specific base, but even after we narrow the search range to numbers with the right amount of digits in their square and cube there's a lot of numbers to check. This system coordinates multiple clients to search more efficiently.
For more background, check out the original article and my findings.
The easiest way to get started is by going to https://nicenumbers.net/search/ and running it in your browser. You'll see live results and everything will be submitted in your name.
If you want to go even faster, you can run the native binaries from the latest release or run the docker image. We usually see a ~2x speedup versus the browser.
# Run the release binary
./nice_client
# Run the docker image
docker run -it --init ghcr.io/wasabipesto/nice_client:3
# Run with a username
./nice_client --username gilgamesh
# Run with 12 threads
./nice_client --threads 12
# Run forever
./nice_client --repeat
# The docker image supports these options too!
docker run -it --init ghcr.io/wasabipesto/nice_client:3 --repeat
# Both versions also support environment variables
docker run -it --init -e NICE_USERNAME=gilgamesh ghcr.io/wasabipesto/nice_client:3You may get slightly more performance by building the binaries yourself. Building the client requires rust and a few other dependencies.
# Install rust and cargo
sudo apt install build-essential curl git
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Clone this repository
git clone https://github.com/wasabipesto/nice.git
cd nice
# Build the client binary
cargo build -r -p nice_client
cd target/release
# Run once with default settings
./nice_clientYou can find various settings and their options with the --help flag:
a client for distributed search of square-cube pandigitals
Usage: nice_client [OPTIONS] [MODE]
Arguments:
[MODE]
The checkout mode to use
Possible values:
- detailed: Get detailed stats on all numbers, important for long-term analytics
- niceonly: Implements optimizations to speed up the search, usually by a factor of around 20. Does not keep statistics and cannot be quickly verified
[env: NICE_MODE=]
[default: detailed]
Options:
--api-base <API_BASE>
The base API URL to connect to
[env: NICE_API_BASE=]
[default: https://api.nicenumbers.net]
--api-max-retries <API_MAX_RETRIES>
If an API call encounters a retryable error, retry with exponential backoff this many times
[env: NICE_API_MAX_RETRIES=]
[default: 10]
-u, --username <USERNAME>
The username to send alongside your contribution
[env: NICE_USERNAME=]
[default: anonymous]
-r, --repeat
Run indefinitely with the current settings
[env: NICE_REPEAT=]
-n, --no-progress
Hide the progress bar
[env: NICE_NO_PROGRESS=]
-t, --threads <THREADS>
Run parallel with this many threads
[env: NICE_THREADS=]
[default: 4]
--prefetch-seconds <PREFETCH_SECONDS>
Keep roughly this many seconds of work claimed ahead of the processor. Set to 0 to force the old single-field prefetch
[env: NICE_PREFETCH_SECONDS=]
[default: 2]
--prefetch-max <PREFETCH_MAX>
Never hold more than this many claimed fields at once
[env: NICE_PREFETCH_MAX=]
[default: 16]
--prefetch-concurrency <PREFETCH_CONCURRENCY>
Allow this many claim requests to be in flight at once
[env: NICE_PREFETCH_CONCURRENCY=]
[default: 4]
-b, --benchmark
Run an offline benchmark sweep and print a detailed report
[env: NICE_BENCHMARK=]
--benchmark-secs <BENCHMARK_SECS>
Approximate time budget for the benchmark sweep, in seconds
[env: NICE_BENCHMARK_SECS=]
[default: 10]
--benchmark-upload
Upload benchmark results without prompting
[env: NICE_BENCHMARK_UPLOAD=]
--telemetry
Attach hardware/config telemetry to each submission
[env: NICE_TELEMETRY=]
--validate
Validate results against the server before submitting
[env: NICE_VALIDATE=]
--gpu
Use GPU acceleration (requires gpu feature)
[env: NICE_GPU=]
--gpu-device <GPU_DEVICE>
GPU device to use (0 for first GPU, 1 for second, etc.)
[env: NICE_GPU_DEVICE=]
[default: 0]
--gpu-backend <GPU_BACKEND>
Which GPU backend to use with --gpu
Possible values:
- auto: Fastest measured order for the mode: detailed tries `cubecl-cuda`, `cubecl`, CUDA, then Vulkan; niceonly tries CUDA, `cubecl`, then Vulkan. See `init_gpu` for the numbers behind the ordering
- cuda: NVIDIA only; requires the CUDA toolkit at runtime for NVRTC
- vulkan: Any Vulkan 1.2 device with `shaderInt64` (AMD, Intel, NVIDIA, llvmpipe). Experimental: only present in builds with the `vulkan` feature, which the `gpu` umbrella no longer includes
- cubecl: `CubeCL` over wgpu: kernels written in Rust, JIT-specialized per base
- cubecl-cuda: `CubeCL` over its native CUDA runtime (needs the `cubecl-cuda` feature)
[env: NICE_GPU_BACKEND=]
[default: auto]
--gpu-wgpu-device <GPU_WGPU_DEVICE>
Which wgpu adapter the `CubeCL` backend uses, in `CubeCL`'s device spelling: `DiscreteGpu(0)`, `IntegratedGpu(1)`, `Cpu`, ... Unset picks the best adapter. This exists because --gpu-device indexes a per-backend namespace (CUDA ordinals != Vulkan ordinals != wgpu adapters), so on a multi-GPU box no single number is right for every backend; the chosen adapter and its graphics API are always logged
[env: NICE_GPU_WGPU_DEVICE=]
-l, --log-level <LOG_LEVEL>
Set the log level (overrides `RUST_LOG` environment variable)
[env: NICE_LOG_LEVEL=]
[possible values: off, error, warn, info, debug, trace]
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
This repository has a common library with most actual functionality included. There are two main binaries: the API server and the client. These can be run directly from source with cargo run -p nice_api or cargo run -p nice_client. There are also binaries for a deamon and some scheduled jobs, and a library for a wasm client.
There are some feature flags that enable specific dependencies:
nice_common/databaseis set automatically from binaries that connect directly to postgres (apiandjobs). This requires thelibpq-devpackage to be installed.nice_client/rustls-tlsis enabled by default and uses rustls for TLS connections, which doesn't require any external dependencies. Disable it and enablenice_client/openssl-tlsto useopenssl.- In order to build the client with GPU acceleration, enable the
nice_client/gpufeature. It is an umbrella over multiple backends below:nice_client/cudais the hand-written CUDA backend (NVIDIA only). It requires the CUDA toolkit at runtime for NVRTC kernel compilation.nice_client/vulkanis the hand-written WGSL backend (experimental — not part of thegpuumbrella); it runs on any Vulkan 1.2 device withshaderInt64(AMD, Intel, NVIDIA, llvmpipe, and MoltenVK on macOS). Every platform it serves is also covered bycubecl, which beats it in detailed mode on all vendors measured, so standard builds omit it; build with--features gpu,vulkanto include it.nice_client/cubeclis the CubeCL backend (kernels written in Rust), running over wgpu: Vulkan on Linux/Windows, Metal on macOS.nice_client/cubecl-cudaadds its native CUDA runtime. Both modes run on the GPU.
Building the WASM client requires wasm-pack.
There are also a few scripts, to be used with rust-script. You can install it with cargo install rust-script then run the scripts directly. It will take a while to build the first time you run it.
If you want to run a copy of this server yourself, a SQL schema file has been provided. You can build the bases and fields with the insert_fields script.
The GPU-enabled client (--features gpu, or the -gpu docker tag) carries multiple backends in one binary and picks one at runtime; the CPU path is always available as a fallback and for verification. Kernels are JIT-compiled per base at first use, so the first field on a new base takes a few extra seconds.
| backend | runs on | needs at runtime |
|---|---|---|
cubecl |
any GPU via wgpu — Vulkan on Linux/Windows, Metal on macOS | a graphics driver |
cubecl-cuda |
NVIDIA | CUDA toolkit (NVRTC) |
cuda |
NVIDIA | CUDA toolkit (NVRTC) |
vulkan (experimental, opt-in build) |
any Vulkan 1.2 device with shaderInt64 |
a Vulkan driver; on macOS also MoltenVK + the Vulkan loader (brew install molten-vk vulkan-loader) |
It's the sixth time. And no comment.