diff --git a/.gitignore b/.gitignore index 0240a06..556b613 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ submission.* target/ +scratch.md diff --git a/docs/AMD_workshop/README.md b/docs/AMD_workshop/README.md new file mode 100644 index 0000000..3b4cc99 --- /dev/null +++ b/docs/AMD_workshop/README.md @@ -0,0 +1,60 @@ +# 🍿 Popcorn CLI - Hackathon Quick Install + +Get started with Popcorn CLI in seconds! Choose your installation method based on your operating system. + +## 🚀 One-Line Install Commands + +### For Linux/macOS/Unix: +```bash +curl -fsSL https://raw.githubusercontent.com/gpu-mode/popcorn-cli/main/install.sh | bash +``` + +### For Windows (PowerShell): +```powershell +powershell -ExecutionPolicy Bypass -Command "iwr -UseBasicParsing https://raw.githubusercontent.com/gpu-mode/popcorn-cli/main/install.ps1 | iex" +``` + +## 📋 Quick Start After Installation + +1. **Restart your terminal** (or run `source ~/.bashrc` / `source ~/.zshrc`) + +2. **Register with GitHub** (one-time setup): + ```bash + popcorn-cli register github + ``` + +3. **Submit your solution:** + ```bash + popcorn-cli submit --gpu MI300 --leaderboard amd-fp8-mm --mode test example.py + ``` + +4. **Interactive mode** (choose GPU and options): + ```bash + popcorn-cli submit my_solution.py + ``` + +## 🛠️ Manual Installation + +If the scripts don't work, you can manually install: + +1. Download the binary for your OS from [releases](https://github.com/gpu-mode/popcorn-cli/releases/tag/v1.1.6) +2. Extract the archive +3. Move the binary to a directory in your PATH +4. Make it executable (Linux/macOS): `chmod +x popcorn-cli` + +## 🆘 Troubleshooting + +### Command not found after installation +- Restart your terminal +- Check if the install directory is in your PATH: + - Linux/macOS: `echo $PATH` + - Windows: `echo $env:PATH` +- Check if POPCORN_API_URL is set to https://discord-cluster-manager-1f6c4782e60a.herokuapp.com + - Linux/macOS: `echo $POPCORN_API_URL` + - Windows: `echo $env:POPCORN_API_URL` + +## 💡 Need Help? + +- Run `popcorn-cli --help` for usage information +- Check the [main repository](https://github.com/gpu-mode/popcorn-cli) and open an issue +- Join the [GPU Mode Discord](https://discord.gg/gpumode) and ask a question in #amd-competition \ No newline at end of file diff --git a/docs/AMD_workshop/example.py b/docs/AMD_workshop/example.py new file mode 100644 index 0000000..b5fd9ab --- /dev/null +++ b/docs/AMD_workshop/example.py @@ -0,0 +1,56 @@ +import torch +from task import input_t, output_t + +def custom_kernel(data: input_t) -> output_t: + """ + Reference implementation of block-scale fp8 gemm + Args: + data: Tuple that expands to: + a: torch.Tensor[float8_e4m3fnuz] of shape [m, k], + b: torch.Tensor[float8_e4m3fnuz] of shape [n, k], + a_scale: torch.Tensor[float32] of shape [m, k // 128], + b_scale: torch.Tensor[float32] of shape [n // 128, k // 128], + c: torch.Tensor[bfloat16] of shape [m, n] + Returns: + Tensor containing output in bf16 + """ + # c: [m, n] is pre-allocated memory to avoid timing allocation overhead. + a, b, a_scale, b_scale, c = data + + # a is M x K in column-major order, we convert here for simplicity. + a = a.contiguous() + a_scale = a_scale.contiguous() + b_scale = b_scale.contiguous() + + # constants + m = a.shape[0] + n = b.shape[0] + k = a.shape[1] + block_shape_n = 128 + block_shape_k = 128 + scale_n = b_scale.shape[0] + scale_k = b_scale.shape[1] + + # Apply scaling to input 'a' + a_scale = a_scale.unsqueeze(-1).repeat(1, 1, block_shape_k) # Shape: [m, scale_k, block_shape_k] + a_scale = a_scale.reshape(m, scale_k * block_shape_k) + a_scale = a_scale[:, :k] + + # Dequantize 'a', in your implementation you should do this at the end. + a = a.to(a_scale.dtype) * a_scale + + # Apply scaling to input 'b' + b_scale = ( + b_scale.view(-1, 1) + .repeat(1, block_shape_n * block_shape_k) + .view(scale_n, scale_k, block_shape_n, block_shape_k) + .permute(0, 2, 1, 3) # Reorder dimensions: [scale_n, blk_n, scale_k, blk_k] + .reshape(scale_n * block_shape_n, scale_k * block_shape_k) + ) + b_scale = b_scale[:n, :k] + + # Dequantize 'b', in your implementation you should do this at the end. + b = b.to(b_scale.dtype) * b_scale + + c[...] = (a @ b.T).to(torch.bfloat16) + return c \ No newline at end of file diff --git a/install.ps1 b/install.ps1 new file mode 100644 index 0000000..0a1e41a --- /dev/null +++ b/install.ps1 @@ -0,0 +1,119 @@ +# Popcorn CLI Hackathon Installer for Windows +# Run with: powershell -ExecutionPolicy Bypass -File install.ps1 + +param( + [switch]$Force = $false +) + +Write-Host "Installing Popcorn CLI for Hackathon (Windows)..." -ForegroundColor Yellow + +# Check if running as administrator (optional but recommended) +$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +if (-not $isAdmin) { + Write-Host "Not running as administrator. Installation will be user-scoped." -ForegroundColor Yellow +} + +# Set variables +$downloadUrl = "https://github.com/gpu-mode/popcorn-cli/releases/latest/download/popcorn-cli-windows.zip" +$tempDir = "$env:TEMP\popcorn-cli-install" +$installDir = "$env:LOCALAPPDATA\popcorn-cli" +$binaryPath = "$installDir\popcorn-cli.exe" + +# Create directories +try { + if (Test-Path $tempDir) { + Remove-Item $tempDir -Recurse -Force + } + New-Item -ItemType Directory -Path $tempDir -Force | Out-Null + New-Item -ItemType Directory -Path $installDir -Force | Out-Null + Write-Host "Created installation directories" -ForegroundColor Green +} catch { + Write-Host "Failed to create directories: $_" -ForegroundColor Red + exit 1 +} + +# Download the binary +Write-Host "Downloading from: $downloadUrl" -ForegroundColor Cyan +try { + $zipPath = "$tempDir\popcorn-cli-windows.zip" + Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath -UseBasicParsing + Write-Host "Download completed" -ForegroundColor Green +} catch { + Write-Host "Download failed: $_" -ForegroundColor Red + exit 1 +} + +# Extract the binary +Write-Host "Extracting binary..." -ForegroundColor Cyan +try { + Expand-Archive -Path $zipPath -DestinationPath $tempDir -Force + + # Find the binary (it might be in a subdirectory) + $binarySource = Get-ChildItem -Path $tempDir -Name "popcorn-cli.exe" -Recurse | Select-Object -First 1 + if ($binarySource) { + $fullBinaryPath = Join-Path $tempDir $binarySource + Copy-Item $fullBinaryPath $binaryPath -Force + Write-Host "Binary extracted and copied" -ForegroundColor Green + } else { + Write-Host "popcorn-cli.exe not found in archive" -ForegroundColor Red + exit 1 + } +} catch { + Write-Host "Extraction failed: $_" -ForegroundColor Red + exit 1 +} + +# Add to PATH +Write-Host "Adding to PATH..." -ForegroundColor Cyan +try { + $userPath = [Environment]::GetEnvironmentVariable("PATH", "User") + if ($userPath -notlike "*$installDir*") { + $newPath = "$installDir;$userPath" + [Environment]::SetEnvironmentVariable("PATH", $newPath, "User") + Write-Host "Added $installDir to user PATH" -ForegroundColor Green + Write-Host "Please restart your terminal or PowerShell session" -ForegroundColor Yellow + } else { + Write-Host "$installDir already in PATH" -ForegroundColor Green + } + + # Also add to current session + $env:PATH = "$installDir;$env:PATH" +} catch { + Write-Host "Could not modify PATH automatically: $_" -ForegroundColor Yellow + Write-Host "Please manually add $installDir to your PATH" -ForegroundColor Yellow +} + +# Cleanup +Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue + +# Test installation +Write-Host "Testing installation..." -ForegroundColor Cyan +try { + $version = & $binaryPath --version 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Host "Installation successful!" -ForegroundColor Green + } else { + Write-Host "Binary installed but may not be working correctly" -ForegroundColor Yellow + } +} catch { + Write-Host "Could not test binary: $_" -ForegroundColor Yellow +} + +Write-Host "" +Write-Host "Popcorn CLI installed and ready for hackathon!" -ForegroundColor Green +Write-Host "" +Write-Host "Quick Start:" -ForegroundColor Cyan +Write-Host " 1. Restart your terminal/PowerShell" -ForegroundColor White +Write-Host " 2. Register with GitHub: popcorn-cli register github" -ForegroundColor White +Write-Host " 3. Submit your solution: popcorn-cli submit --gpu MI300 --leaderboard amd-fp8-mm --mode test " -ForegroundColor White +Write-Host "" +Write-Host "Hackathon mode features:" -ForegroundColor Cyan +Write-Host " - API URL pre-configured" -ForegroundColor White +Write-Host " - GitHub authentication (no Discord setup needed)" -ForegroundColor White +Write-Host " - All modes available: test, benchmark, leaderboard, profile" -ForegroundColor White +Write-Host " - Clean user identification" -ForegroundColor White +Write-Host "" +Write-Host "Need help? Run: popcorn-cli --help" -ForegroundColor White +Write-Host "Example: popcorn-cli submit --gpu MI300 --leaderboard amd-fp8-mm --mode test example.py" -ForegroundColor White +Write-Host "" +Write-Host "Installation location: $installDir" -ForegroundColor Gray \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..80e1dec --- /dev/null +++ b/install.sh @@ -0,0 +1,139 @@ +#!/bin/bash + +set -e + +# Popcorn CLI Hackathon Installer (Unix/Linux/macOS) +# For Windows users: Use install.ps1 instead +echo "🍿 Installing Popcorn CLI for Hackathon (Unix/Linux/macOS)..." + +# Check if we're on Windows +if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin" ]]; then + echo "⚠️ Detected Windows environment" + echo "For native Windows, please use install.ps1 instead:" + echo " powershell -ExecutionPolicy Bypass -File install.ps1" + echo "" + echo "This script will continue assuming you're in a Unix-like environment (WSL/Git Bash/MSYS2)" + read -p "Continue? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 0 + fi +fi + +# Detect OS +OS="" +ARCH="" +BINARY_NAME="" +EXTENSION="" + +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + OS="linux" + EXTENSION=".tar.gz" + BINARY_NAME="popcorn-cli" +elif [[ "$OSTYPE" == "darwin"* ]]; then + OS="macos" + EXTENSION=".tar.gz" + BINARY_NAME="popcorn-cli" +elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin" ]]; then + OS="windows" + EXTENSION=".zip" + BINARY_NAME="popcorn-cli.exe" +else + echo "❌ Unsupported operating system: $OSTYPE" + exit 1 +fi + +echo "✅ Detected OS: $OS" + +# Download URL +DOWNLOAD_URL="https://github.com/gpu-mode/popcorn-cli/releases/latest/download/popcorn-cli-${OS}${EXTENSION}" +TEMP_DIR="/tmp/popcorn-cli-install" +INSTALL_DIR="$HOME/.local/bin" + +# Create directories +mkdir -p "$TEMP_DIR" +mkdir -p "$INSTALL_DIR" + +echo "📥 Downloading from: $DOWNLOAD_URL" + +# Download the binary +if command -v curl >/dev/null 2>&1; then + curl -L -o "$TEMP_DIR/popcorn-cli${EXTENSION}" "$DOWNLOAD_URL" +elif command -v wget >/dev/null 2>&1; then + wget -O "$TEMP_DIR/popcorn-cli${EXTENSION}" "$DOWNLOAD_URL" +else + echo "❌ Neither curl nor wget found. Please install one of them." + exit 1 +fi + +echo "📦 Extracting binary..." + +# Extract the binary +cd "$TEMP_DIR" +if [[ "$EXTENSION" == ".tar.gz" ]]; then + tar -xzf "popcorn-cli${EXTENSION}" +elif [[ "$EXTENSION" == ".zip" ]]; then + unzip "popcorn-cli${EXTENSION}" +fi + +# Find and move the binary +if [[ -f "$BINARY_NAME" ]]; then + chmod +x "$BINARY_NAME" + mv "$BINARY_NAME" "$INSTALL_DIR/" + echo "✅ Binary installed to $INSTALL_DIR/$BINARY_NAME" +else + echo "❌ Binary not found after extraction" + exit 1 +fi + +# Add to PATH +SHELL_RC="" +if [[ -n "$ZSH_VERSION" ]]; then + SHELL_RC="$HOME/.zshrc" +elif [[ -n "$BASH_VERSION" ]]; then + SHELL_RC="$HOME/.bashrc" +else + # Try to detect shell + case "$SHELL" in + */zsh) + SHELL_RC="$HOME/.zshrc" + ;; + */bash) + SHELL_RC="$HOME/.bashrc" + ;; + *) + SHELL_RC="$HOME/.profile" + ;; + esac +fi + +# Check if PATH already contains the directory +if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then + echo "🔧 Adding $INSTALL_DIR to PATH in $SHELL_RC" + echo "" >> "$SHELL_RC" + echo "# Added by Popcorn CLI installer" >> "$SHELL_RC" + echo "export PATH=\"$INSTALL_DIR:\$PATH\"" >> "$SHELL_RC" + export PATH="$INSTALL_DIR:$PATH" +else + echo "✅ $INSTALL_DIR already in PATH" +fi + +# Cleanup +rm -rf "$TEMP_DIR" + +echo "" +echo "🎉 Popcorn CLI installed and ready for hackathon!" +echo "" +echo "📋 Quick Start:" +echo " 1. Restart your terminal or run: source $SHELL_RC" +echo " 2. Register with GitHub: popcorn-cli register github" +echo " 3. Submit your solution: popcorn-cli submit --gpu MI300 --leaderboard amd-fp8-mm --mode test " +echo "" +echo "🚀 Hackathon mode features:" +echo " - ✅ API URL pre-configured" +echo " - ✅ GitHub authentication (no Discord setup needed)" +echo " - ✅ All modes available: test, benchmark, leaderboard, profile" +echo " - ✅ Clean user identification" +echo "" +echo "💡 Need help? Run: popcorn-cli --help" +echo "🔗 Example: popcorn-cli submit --gpu MI300 --leaderboard amd-fp8-mm --mode test example.py" \ No newline at end of file diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index f52c6b6..617bfad 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -111,11 +111,12 @@ pub async fn execute(cli: Cli) -> Result<()> { let config = load_config()?; let cli_id = config.cli_id.ok_or_else(|| { anyhow!( - "cli_id not found in config file ({}). Please run `popcorn register` first.", + "cli_id not found in config file ({}). Please run 'popcorn-cli register' first.", get_config_path() .map_or_else(|_| "unknown path".to_string(), |p| p.display().to_string()) ) })?; + // Use filepath from Submit command first, fallback to top-level filepath let final_filepath = filepath.or(cli.filepath); submit::run_submit_tui( diff --git a/src/main.rs b/src/main.rs index ccf767c..b25bcc3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,15 +10,12 @@ use std::process; #[tokio::main] async fn main() { - // Parse command line arguments - let cli = Cli::parse(); - - // Popcorn API URL check (needed for most commands) - // We might want to move this check inside specific commands later if some don't need it. + // Set the API URL FIRST - before anything else if env::var("POPCORN_API_URL").is_err() { - eprintln!("POPCORN_API_URL is not set. Please set it to the URL of the Popcorn API."); - process::exit(1); + env::set_var("POPCORN_API_URL", "https://discord-cluster-manager-1f6c4782e60a.herokuapp.com"); } + // Parse command line arguments + let cli = Cli::parse(); // Execute the parsed command if let Err(e) = cmd::execute(cli).await {