Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@
"# Configuration for the algorithm\n",
"@dataclass\n",
"class PowerIterationConfig:\n",
" dim: int = 4096 # Matrix size (dim x dim)\n",
" dominance: float = 0.1 # How much larger the top eigenvalue is (controls convergence, higher == faster)\n",
" max_steps: int = 400 # Maximum iterations\n",
" check_frequency: int = 10 # Check for convergence every N steps\n",
" dim: int = 10000 # Matrix size (dim x dim)\n",
" dominance: float = 0.05 # How much larger the top eigenvalue is (controls convergence, higher == faster)\n",
" max_steps: int = 1000 # Maximum iterations\n",
" check_frequency: int = 25 # Check for convergence every N steps\n",
" progress: bool = True # Print progress logs\n",
" residual_threshold: float = 1e-10 # Stop if error is below this"
]
Expand Down Expand Up @@ -194,7 +194,7 @@
" break\n",
"\n",
" # Run intermediate steps without checking residual to save compute.\n",
" for _ in range(cfg.check_frequency - 1):\n",
" for _ in range(i + 1, min(i + cfg.check_frequency, cfg.max_steps)):\n",
" y = A @ x\n",
" x = y / np.linalg.norm(y)\n",
"\n",
Expand Down Expand Up @@ -274,7 +274,7 @@
" break\n",
"\n",
" # Run intermediate steps without checking residual to save compute\n",
" for _ in range(cfg.check_frequency - 1):\n",
" for _ in range(i + 1, min(i + cfg.check_frequency, cfg.max_steps)):\n",
" y = A @ x\n",
" x = y / np.linalg.norm(y)\n",
"\n",
Expand Down Expand Up @@ -476,7 +476,7 @@
"\n",
"**Explore the impact of changing the following parameters:**\n",
"\n",
"1. **Problem Size (`dim`):** How does the GPU speedup change as you increase or decrease the matrix dimensions? Try values like 1024, 2048, 4096, 8192.\n",
"1. **Problem Size (`dim`):** How does the GPU speedup change as you decrease the matrix dimensions? Try values like 1024, 2048, 4096, 8192.\n",
"\n",
"2. **Compute Workload (`max_steps` and `dominance`):** The `dominance` parameter controls how quickly the algorithm converges. A smaller dominance means eigenvalues are closer together, requiring more iterations. How does this affect the CPU vs GPU comparison?\n",
"\n",
Expand All @@ -494,7 +494,7 @@
"source": [
"# Try different configurations here!\n",
"# Example:\n",
"# cfg_large = PowerIterationConfig(dim=8192, progress=False)\n",
"# cfg_smaller = PowerIterationConfig(dim=8192, progress=False)\n",
"# cfg_slow_converge = PowerIterationConfig(dominance=0.01, progress=False)\n",
"# cfg_frequent_check = PowerIterationConfig(check_frequency=1, progress=True)\n",
"\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"5. [Better Visibility with NVTX](#5-Better-Visibility-with-NVTX)\n",
"6. [Implementing Asynchrony](#6-Implementing-Asynchrony)\n",
"7. [Performance Analysis](#7-Performance-Analysis)\n",
"8. [Balancing CPU I/O and GPU Compute](#8-Balancing-CPU-I/O-and-GPU-Compute)\n",
"\n",
"### 1. Introduction and Setup\n",
"\n",
Expand Down Expand Up @@ -49,7 +50,10 @@
" open(\"/accelerated-computing-hub-installed\", \"a\").close()\n",
" print(\"All packages installed.\")\n",
"\n",
"import nsightful"
"import nsightful\n",
"from jupyter_dark_detect import is_dark\n",
"import matplotlib.pyplot as plt\n",
"plt.style.use('dark_background' if is_dark() else 'default')"
]
},
{
Expand Down Expand Up @@ -93,15 +97,16 @@
"import cupy as cp\n",
"import cupyx as cpx\n",
"import nvtx\n",
"import sys\n",
"import time\n",
"from dataclasses import dataclass\n",
"\n",
"@dataclass\n",
"class PowerIterationConfig:\n",
" dim: int = 8192\n",
" dim: int = 19000\n",
" dominance: float = 0.05\n",
" max_steps: int = 1000\n",
" check_frequency: int = 15\n",
" max_steps: int = 400\n",
" check_frequency: int = 25 if len(sys.argv) < 2 else int(sys.argv[1])\n",
" progress: bool = True\n",
" residual_threshold: float = 1e-10\n",
"\n",
Expand Down Expand Up @@ -135,7 +140,7 @@
" if res < cfg.residual_threshold:\n",
" break\n",
"\n",
" for _ in range(cfg.check_frequency - 1):\n",
" for _ in range(i + 1, min(i + cfg.check_frequency, cfg.max_steps)):\n",
" y = A_gpu @ x # We have to use `A_gpu` here as well.\n",
" x = y / cp.linalg.norm(y) # Normalize for next step.\n",
"\n",
Expand Down Expand Up @@ -284,15 +289,16 @@
"import cupy as cp\n",
"import cupyx as cpx\n",
"import nvtx\n",
"import sys\n",
"import time\n",
"from dataclasses import dataclass\n",
"\n",
"@dataclass\n",
"class PowerIterationConfig:\n",
" dim: int = 8192\n",
" dim: int = 19000\n",
" dominance: float = 0.05\n",
" max_steps: int = 1000\n",
" check_frequency: int = 15\n",
" max_steps: int = 400\n",
" check_frequency: int = 25 if len(sys.argv) < 2 else int(sys.argv[1])\n",
" progress: bool = True\n",
" residual_threshold: float = 1e-10\n",
"\n",
Expand Down Expand Up @@ -421,6 +427,72 @@
"!nsys export --type sqlite --quiet true --force-overwrite true power_iteration__async.nsys-rep\n",
"nsightful.display_nsys_sqlite_file_in_notebook(\"power_iteration__async.sqlite\", title=\"Power Iteration - Async\")"
]
},
{
"cell_type": "markdown",
"id": "b8a12d4e",
"metadata": {},
"source": [
"### 8. Balancing CPU I/O and GPU Compute\n",
"\n",
"Our asynchronous implementation overlaps checkpoint I/O on the CPU with power-iteration steps on the GPU. `check_frequency` controls how many GPU steps run between residual checks and checkpoints. A smaller value produces output more frequently, but may not provide enough GPU work to hide the I/O. A larger value provides more GPU work to overlap with the I/O, but delays output and convergence checks.\n",
"\n",
"**TODO:** Sweep check frequencies from 20 through 30 in increments of 1 and determine the output frequency with the lowest execution time. Run `python power_iteration__async.py <check_frequency>` for each value, record the final time reported by the script, and plot the results."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c6f42a91",
"metadata": {},
"outputs": [],
"source": [
"check_frequencies = list(range(20, 31))\n",
"async_durations = []\n",
"\n",
"print(\"Sweeping async check frequencies...\")\n",
"print(\"=\" * 45)\n",
"print(f\"{'Check Frequency':>18} | {'Time (ms)':>12}\")\n",
"print(\"-\" * 45)\n",
"\n",
"for check_frequency in check_frequencies:\n",
" # TODO: Run power_iteration__async.py with check_frequency, extract\n",
" # its reported time in milliseconds, and append it to async_durations.\n",
" pass\n",
"\n",
"print(\"=\" * 45)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d3e7b580",
"metadata": {},
"outputs": [],
"source": [
"# TODO: Find the check frequency with the shortest execution time and\n",
"# display a performance graph. Highlight the optimal point."
]
},
{
"cell_type": "markdown",
"id": "e91c4a27",
"metadata": {},
"source": [
"Finally, profile the optimal check frequency. In the trace, compare the CPU I/O region with the GPU compute between checks. Does the GPU compute fully hide the I/O?"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f24b6c39",
"metadata": {},
"outputs": [],
"source": [
"!nsys profile --cuda-event-trace=false --capture-range=cudaProfilerApi --capture-range-end=stop --force-overwrite true -o power_iteration__async__optimal python power_iteration__async.py {optimal_check_frequency}\n",
"!nsys export --type sqlite --quiet true --force-overwrite true power_iteration__async__optimal.nsys-rep\n",
"nsightful.display_nsys_sqlite_file_in_notebook(\"power_iteration__async__optimal.sqlite\", title=f\"Power Iteration - Async - Check Frequency {optimal_check_frequency}\")"
]
}
],
"metadata": {
Expand Down
Loading