diff --git a/.github/workflows/update-quick-start-module.yml b/.github/workflows/update-quick-start-module.yml index bf6956011c9f..09098abd403b 100644 --- a/.github/workflows/update-quick-start-module.yml +++ b/.github/workflows/update-quick-start-module.yml @@ -7,16 +7,24 @@ on: paths: - .github/workflows/update-quick-start-module.yml - scripts/gen_quick_start_module.py + - scripts/gen_additional_platforms.py - _includes/quick-start-module.js - _includes/quick_start_local.html + - _includes/quick-start-additional-platforms.js + - _includes/quick_start_additional_platforms.html + - _additional_platforms/*.json push: branches: site paths: - .github/workflows/update-quick-start-module.yml - scripts/gen_quick_start_module.py + - scripts/gen_additional_platforms.py - _includes/quick-start-module.js - _includes/quick_start_local.html + - _includes/quick-start-additional-platforms.js + - _includes/quick_start_additional_platforms.html + - _additional_platforms/*.json workflow_dispatch: jobs: @@ -116,3 +124,38 @@ jobs: body: > This PR is auto-generated. It updates Getting Started page labels: automated pr + + update-additional-platform: + runs-on: "ubuntu-latest" + environment: pytorchbot-env + steps: + - name: Checkout pytorch.github.io + uses: actions/checkout@v2 + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + architecture: x64 + - name: Generate quick-start-additional-platforms.js + shell: bash + run: | + set -ex + python3 ./scripts/gen_additional_platforms.py + - name: Create Issue if failed + uses: dacbd/create-issue-action@main + if: ${{ failure() }} + with: + title: Updating additional platforms quick start module failed + token: ${{secrets.PYTORCHBOT_TOKEN}} + assignees: ${{github.actor}} + labels: bug + body: Updating additional platforms quick start module failed, please fix the update script or check JSON files + - name: Create Pull Request + uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.PYTORCHBOT_TOKEN }} + commit-message: Update quick-start-additional-platforms.js + title: '[Additional Platforms] Update quick-start-additional-platforms.js' + body: > + This PR is auto-generated. It updates the Additional Platforms Getting Started page + labels: automated pr diff --git a/README.md b/README.md index 7f661d20a18e..e0bb2e371477 100644 --- a/README.md +++ b/README.md @@ -92,3 +92,4 @@ PyTorch repo [README.md](https://github.com/pytorch/pytorch/blob/master/README.m * Information about contributing to PyTorch Tutorials can be found in the tutorials [README.md](https://github.com/pytorch/tutorials/blob/master/README.md). * Additional contribution information can be found in [PyTorch CONTRIBUTING.md](https://github.com/pytorch/pytorch/blob/master/CONTRIBUTING.md). +* To add additional accelerators to pytorch.org, please refer to [additional_platforms.md](additional_platforms.md). diff --git a/_get_started/get-started-additional-platforms.md b/_get_started/get-started-additional-platforms.md new file mode 100644 index 000000000000..eb44bb4b1b9e --- /dev/null +++ b/_get_started/get-started-additional-platforms.md @@ -0,0 +1,27 @@ +--- +layout: get_started +title: Additional Platforms +permalink: /get-started/additional-platforms/ +background-class: get-started-background +body-class: get-started +order: 1 +published: true +get-started-additional: true +--- + +
+
+
+ {% include quick_start_additional_platforms.html %} +
+
+
+ +--- +
+ +
+ + + + diff --git a/_get_started/get-started-locally.md b/_get_started/get-started-locally.md index 6a95566a3946..6aa17b1d1ae0 100644 --- a/_get_started/get-started-locally.md +++ b/_get_started/get-started-locally.md @@ -20,6 +20,8 @@ redirect_from: "/get-started/" +

Could not find the right platform for your hardware? See the PyTorch Additional Platforms page.

+ --- {% capture mac %} diff --git a/_includes/quick-start-additional-platforms.js b/_includes/quick-start-additional-platforms.js new file mode 100644 index 000000000000..e7ee664755b8 --- /dev/null +++ b/_includes/quick-start-additional-platforms.js @@ -0,0 +1,279 @@ +// ===================================================== +// Additional Platforms Quick Start Module +// ===================================================== + +// Platform data loaded from JSON files (generated by gen_additional_platforms.py) +var ecosystemPlatformData = {{ platformData }}; + +// HTML content loaded from _get_started/additional_platforms/ directory +// (pre-converted by Python script with syntax highlighting) +var ecosystemHtmlContent = {{ markdownContent }}; + +// Get platform IDs from loaded data +var ecosystemPlatformIds = Object.keys(ecosystemPlatformData); + +// Ecosystem platform selections - simplified (no pm, no version) +var ecosystemOpts = { + build: 'stable', + os: 'linux', + platform: null +}; + +// Parse URL parameters for pre-selection +function parseUrlParams() { + var params = new URLSearchParams(window.location.search); + var platform = params.get('platform'); + var build = params.get('build') || 'stable'; + var os = params.get('os') || 'linux'; + + return { + platform: platform, + build: build, + os: os + }; +} + +// Apply URL parameter selections +function applyUrlSelections() { + var urlParams = parseUrlParams(); + + // Apply build selection + if (urlParams.build && ecosystemOpts.build !== urlParams.build) { + ecosystemOpts.build = urlParams.build; + $('.pytorch-build > .option').removeClass('selected'); + $('.pytorch-build > .option#' + urlParams.build).addClass('selected'); + } + + // Apply OS selection + if (urlParams.os && ecosystemOpts.os !== urlParams.os) { + ecosystemOpts.os = urlParams.os; + $('.os-ecosystem > .option').removeClass('selected'); + $('.os-ecosystem > .option#' + urlParams.os).addClass('selected'); + } + + // Apply platform selection + if (urlParams.platform && ecosystemPlatformData[urlParams.platform]) { + ecosystemOpts.platform = urlParams.platform; + $('.compute-platform > .option').removeClass('selected'); + $('.compute-platform > .option#' + urlParams.platform).addClass('selected'); + updateEcosystemCommand(); + updatePlatformContentDisplay(); + } +} + +// Initialize additional platforms when document is ready +$(function() { + initPlatformContentContainer(); + initAdditionalPlatforms(); + initAdditionalPlatformButtons(); + updatePlatformButtonStates(); + syncComputePlatformHeight(); + initPlatformContentDisplay(); + + // Apply URL parameter selections after initialization + applyUrlSelections(); +}); + +// Initialize platform content container - dynamically create divs for each platform +function initPlatformContentContainer() { + var container = $('#additional-platforms-installation'); + if (!container.length) return; + + // Clear any existing static content + container.empty(); + + // Create platform content divs dynamically based on HTML content + ecosystemPlatformIds.forEach(function(platformId) { + if (ecosystemHtmlContent[platformId]) { + var contentDiv = $('
'); + // HTML content is already pre-converted with syntax highlighting + contentDiv.html(ecosystemHtmlContent[platformId]); + container.append(contentDiv); + } + }); +} + +// Note: Markdown is pre-converted to HTML by Python script (gen_additional_platforms.py) +// using markdown library with codehilite extension for syntax highlighting. +// No need for client-side markdown parsing. + +// Initialize platform content display - hide all initially +function initPlatformContentDisplay() { + $('#additional-platforms-installation .platform-content').hide(); +} + +// Sync left heading height with right compute platform buttons height +function syncComputePlatformHeight() { + var rightHeight = $('.compute-platform').outerHeight(); + if (rightHeight > 0) { + $('.compute-platform-heading').css('min-height', rightHeight + 'px'); + } +} + +// Populate compute platform buttons +function initAdditionalPlatformButtons() { + var platformRow = $('.compute-platform'); + if (!platformRow.length) return; + + // Generate platform buttons + ecosystemPlatformIds.forEach(function(platformId) { + var platform = ecosystemPlatformData[platformId]; + if (!platform) return; + var displayName = platform.name; + var btn = $('
' + displayName + '
'); + platformRow.append(btn); + }); + + // Sync height after buttons are generated + syncComputePlatformHeight(); + + // Bind platform button click + $('.compute-platform > .option').on('click', function() { + var platformId = this.id; + var platform = ecosystemPlatformData[platformId]; + if (!platform) return; + + // Check if supported on current OS + var supportedOS = getSupportedOS(platformId); + if (!supportedOS.includes(ecosystemOpts.os)) { + $('#command').html('' + platform.name + ' is not supported on ' + ecosystemOpts.os + ''); + return; + } + + // Select this platform + $('.compute-platform > .option').removeClass('selected'); + $(this).addClass('selected'); + ecosystemOpts.platform = platformId; + + updateEcosystemCommand(); + updatePlatformContentDisplay(); + }); +} + +// Get supported OS list from platform data structure +function getSupportedOS(platformId) { + var platform = ecosystemPlatformData[platformId]; + if (!platform) return []; + + var osSet = new Set(); + ['stable', 'preview'].forEach(function(build) { + if (platform[build]) { + Object.keys(platform[build]).forEach(function(os) { + osSet.add(os); + }); + } + }); + return Array.from(osSet); +} + +// Update platform button states (disabled/enabled) based on OS +function updatePlatformButtonStates() { + $('.compute-platform > .option').each(function() { + var platformId = this.id; + if (!platformId) return; + + var supportedOS = getSupportedOS(platformId); + var isSupported = supportedOS.includes(ecosystemOpts.os); + + if (isSupported) { + $(this).css('text-decoration', ''); + } else { + $(this).css('text-decoration', 'line-through'); + } + }); + + // If currently selected platform is not supported on new OS, deselect it + if (ecosystemOpts.platform) { + var supportedOS = getSupportedOS(ecosystemOpts.platform); + if (!supportedOS.includes(ecosystemOpts.os)) { + ecosystemOpts.platform = null; + $('.compute-platform > .option').removeClass('selected'); + $('#command').html('Select a compute platform to see the installation command.'); + updatePlatformContentDisplay(); + } + } +} + +// Update platform content display based on selected platform +function updatePlatformContentDisplay() { + // Hide all platform content first + $('#additional-platforms-installation .platform-content').hide(); + + // Show selected platform content + if (ecosystemOpts.platform) { + $('#additional-platforms-installation .platform-content.' + ecosystemOpts.platform).show(); + } +} + +// Initialize all click events for build/os blocks +function initAdditionalPlatforms() { + // PyTorch Build + $('.pytorch-build > .option').on('click', function() { + $('.pytorch-build > .option').removeClass('selected'); + $(this).addClass('selected'); + ecosystemOpts.build = this.id; + updateEcosystemCommand(); + }); + + // OS - with platform support check + $('.os-ecosystem > .option').on('click', function() { + $('.os-ecosystem > .option').removeClass('selected'); + $(this).addClass('selected'); + ecosystemOpts.os = this.id; + + updatePlatformButtonStates(); + updateEcosystemCommand(); + }); +} + +// Update ecosystem command based on selections - simplified +function updateEcosystemCommand() { + if (!ecosystemOpts.platform) { + $('#command').html('Select a compute platform to see the installation command.'); + $('#support-channel').html('Select a compute platform to see the support channel.'); + return; + } + + var platform = ecosystemPlatformData[ecosystemOpts.platform]; + if (!platform) { + $('#command').html('Loading platform data...'); + $('#support-channel').html('Loading platform data...'); + return; + } + + // Check if OS is supported + var supportedOS = getSupportedOS(ecosystemOpts.platform); + if (!supportedOS.includes(ecosystemOpts.os)) { + $('#command').html('' + platform.name + ' is not supported on ' + ecosystemOpts.os + ''); + $('#support-channel').html('Select a supported platform to see the support channel.'); + return; + } + + // Get command directly from platform[build][os] + try { + var buildData = platform[ecosystemOpts.build]; + if (!buildData || !buildData[ecosystemOpts.os]) { + $('#command').html('Configuration not available for this combination'); + $('#support-channel').html('Select a valid combination to see the support channel.'); + return; + } + + var cmd = buildData[ecosystemOpts.os]; + + if (cmd) { + $('#command').html('
' + cmd + '
'); + } else { + $('#command').html('Configuration not available for this combination'); + } + + // Update support channel + if (platform.support_channel) { + $('#support-channel').html('' + platform.support_channel + ''); + } else { + $('#support-channel').html('No support channel available for this platform.'); + } + } catch (e) { + $('#command').html('Configuration not available for this combination'); + $('#support-channel').html('Configuration not available'); + } +} diff --git a/_includes/quick_start_additional_platforms.html b/_includes/quick_start_additional_platforms.html new file mode 100644 index 000000000000..11ca339d0d35 --- /dev/null +++ b/_includes/quick_start_additional_platforms.html @@ -0,0 +1,79 @@ +

In the selector below, you will find compute platforms and configurations provided by our partners and community members. Choose your preferences and run the provided command.

+ +
+
+
+
Compute Platform
+
+
+
PyTorch Build
+
+
+
Your OS
+
+
+
Run this Command:
+
+
+
Support Channel:
+
+
+ +
+ +
+
+
Compute Platform
+
+ +
+ + +
+
+
PyTorch Build
+
+
+
Stable
+
+
+
Preview (Nightly)
+
+
+ + +
+
+
Your OS
+
+
+
Linux
+
+
+
Windows
+
+
+ + +
+
+
Run this Command:
+
+
+
Select a compute platform to see the installation command.
+
+
+ + +
+
+
Support Channel:
+
+
+
Select a compute platform to see the support channel.
+
+
+
+
+ +

Note: More platform-specific details will appear below upon selection. Please scroll down.

diff --git a/_sass/get-started.scss b/_sass/get-started.scss index ca3c335c41fe..a46dcd88614b 100644 --- a/_sass/get-started.scss +++ b/_sass/get-started.scss @@ -65,12 +65,12 @@ } .get-started-nav-link { - padding-left: rem(20px); - padding-right: rem(20px); + padding-left: rem(10px); + padding-right: rem(10px); @include desktop { - padding-left: rem(30px); - padding-right: rem(30px); + padding-left: rem(10px); + padding-right: rem(10px); } } diff --git a/_sass/quick-start-module.scss b/_sass/quick-start-module.scss index 884df6705cbd..416f57d010ed 100644 --- a/_sass/quick-start-module.scss +++ b/_sass/quick-start-module.scss @@ -160,6 +160,25 @@ } } + #support-channel { + background-color: $light_grey; + cursor: default; + color: #4a4a4a; + + &:hover { + background-color: $light_grey; + color: #4a4a4a; + } + + a { + @include desktop { + &:hover { + color: $orange; + } + } + } + } + .command-container { display: table; width: 100%; diff --git a/additional_platforms.md b/additional_platforms.md new file mode 100644 index 000000000000..a5dd16c94bd9 --- /dev/null +++ b/additional_platforms.md @@ -0,0 +1,145 @@ +# Additional Platforms Integration Guide + +## Overview + +The PyTorch "Additional Platforms" page allows hardware vendors and platform providers to showcase their PyTorch-compatible accelerators and computing platforms. This guide explains how third-party vendors can add their platforms to the PyTorch "Get Started" page. + +## Minimum Requirements + +To have your platform added to the PyTorch Additional Platforms page, please ensure: + +1. **Stable PyTorch Build:** Your platform must have a stable, nightly, and publicly available PyTorch build +2. **Documentation:** Comprehensive documentation for users +3. **Support Channel:** A way for users to get help (Discord, GitHub issues, forum, etc.) +4. **Active Maintenance:** The platform should be actively maintained and updated for new PyTorch versions +5. **OS support**: Your platforms should support at least Linux system + +## Directory Structure + +``` +pytorch.github.io/ +├── _additional_platform/ # JSON configuration files +│ ├── acc1.json # Platform configuration +│ ├── acc2.json +│ └── ... +├── _get_started/ +│ └── additional_platforms/ # Markdown documentation files +│ ├── acc1.md # Platform installation guide +│ ├── acc2.md +│ └── ... +└── scripts/ + └── gen_additional_platforms.py # Generation script +``` + +## Step-by-Step Guide + +### Step 1: Create a JSON Configuration File + +Create a JSON file in the `_additional_platforms/` directory. The filename should match your platform ID (e.g., `myplatform.json`). + +**Location:** `_additional_platforms/{platform_id}.json` + +**Required Fields:** + +```json +{ + "name": "Platform Name", + "vendor": "Vendor Name", + "support_channel": "https://discord.gg/vendor", + "stable": { + "linux": "pip3 install torch torchvision --index-url https://download.pytorch.org/whl/platform/sdk80" + }, + "preview": { + "linux": "pip3 install torch torchvision --pre --index-url https://download.pytorch.org/whl/nightly/platform/sdk80" + } +} +``` + +**Field Descriptions:** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | Yes | Display name of the platform shown in the selector | +| `vendor` | string | Yes | Name of the vendor/company providing the platform | +| `support_channel` | string | Yes | URL to support channel (Discord, Slack, etc.) | +| `stable` | object | Yes | Installation commands for stable releases | +| `preview` | object | Yes | Installation commands for preview/nightly releases | + +**Installation Commands Structure:** + +The `stable` and `preview` objects support the following OS keys: +- `linux` - Linux installation command (Required) +- `windows` - Windows installation command (Optional) + +Example with multiple OS support: + +```json +{ + "stable": { + "linux": "pip3 install torch torchvision --index-url https://download.pytorch.org/whl/myplatform/linux", + "windows": "pip3 install torch torchvision --index-url https://download.pytorch.org/whl/myplatform/windows", + } +} +``` + +### Step 2: Create a Markdown Documentation File + +Create a Markdown file in the `_get_started/additional_platforms/` directory. The filename must match the platform ID used in the JSON file. + +**Location:** `_get_started/additional_platforms/{platform_id}.md` + +**Recommended Structure:** + +````markdown +# Installing on {Platform Name} Platform + +{Brief description of the platform and what it offers.} + +## Prerequisites + +### Hardware Requirements + +* {Hardware requirement 1} +* {Hardware requirement 2} + +### Software Requirements + +* Python {version range} +* {Platform} SDK {version} or later + +## Installation + +### pip + +Use the pip package manager to install PyTorch with {Platform} support. Select your preferred options in the selector above to get the installation command. + +## Verification + +To ensure that PyTorch was installed correctly with {Platform} support, run the following code: + +```python +import torch +print(torch.__version__) + +# Check {Platform} availability +if torch.backends.{platform_id}.is_available(): + print("{Platform} is available!") + print(f"{Platform} devices: {torch.backends.{platform_id}.device_count()}") +else: + print("{Platform} is not available.") + +``` + +## Documentation + +For more information, please visit the [{Platform} Documentation](https://docs.vendor.com/platform). +```` + +### Step 3: Submit a Pull Request + +1. Fork the [pytorch.github.io](https://github.com/pytorch/pytorch.github.io) repository +2. Add your JSON and Markdown files in the appropriate directories +3. Submit a pull request with: + - A clear title describing the platform you're adding + - A brief description of the platform + - Contact information for follow-up questions diff --git a/scripts/gen_additional_platforms.py b/scripts/gen_additional_platforms.py new file mode 100644 index 000000000000..2afb863f57e1 --- /dev/null +++ b/scripts/gen_additional_platforms.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +""" +Generates additional platforms quick start module for +https://pytorch.org/get-started/additional-platforms/ page. + +This script reads all JSON files from _additional_platforms/ directory, +combines them, and generates the quick-start-additional-platforms.js file. +It also reads markdown files from _get_started/additional_platforms/ directory +and embeds them for dynamic content loading. + +Usage: + python3 scripts/gen_additional_platforms.py + +The script will: +1. Read all JSON files from _additional_platforms/ directory +2. Read all MD files from _get_started/additional_platforms/ directory +3. Combine platform data into a single object (keyed by filename) +4. Replace template placeholders in _includes/quick-start-additional-platforms.js +5. Output the result to assets/quick-start-additional-platforms.js +""" + +import json +from pathlib import Path +from typing import Dict, Any +import markdown +from markdown.extensions.codehilite import CodeHiliteExtension +import re + +BASE_DIR = Path(__file__).parent.parent +ADDITIONAL_PLATFORM_DIR = BASE_DIR / "_additional_platforms" +MARKDOWN_DIR = BASE_DIR / "_get_started" / "additional_platforms" +INCLUDES_DIR = BASE_DIR / "_includes" +ASSETS_DIR = BASE_DIR / "assets" + + +def read_platform_json_files() -> Dict[str, Any]: + """Read all JSON files from _additional_platforms directory.""" + platform_data = {} + + if not ADDITIONAL_PLATFORM_DIR.exists(): + print(f"Warning: {ADDITIONAL_PLATFORM_DIR} does not exist") + return platform_data + + for json_file in ADDITIONAL_PLATFORM_DIR.glob("*.json"): + try: + content = json_file.read_text() + data = json.loads(content) + # Use filename (without .json) as platform_id + platform_id = json_file.stem + platform_data[platform_id] = data + print(f"Loaded platform: {platform_id} from {json_file.name}") + except json.JSONDecodeError as e: + print(f"Error parsing {json_file.name}: {e}") + + return platform_data + + +def convert_markdown_to_html(markdown_text: str) -> str: + """Convert markdown to HTML with syntax highlighting. + + Uses Python markdown library with codehilite extension for syntax highlighting. + This produces HTML similar to Jekyll's markdownify filter. + """ + # Remove Jekyll/Kramdown special syntax (e.g., {:.no_toc}, {: #id}) + html_text = re.sub(r'\{:[^}]*\}', '', markdown_text) + + # Convert markdown to HTML with codehilite extension + # Codehilite uses Pygments for syntax highlighting (similar to Rouge used by Jekyll) + md = markdown.Markdown(extensions=[ + CodeHiliteExtension( + css_class='highlight', + guess_lang=False, + linenums=False + ), + 'fenced_code', + 'tables', + 'toc' + ]) + + html = md.convert(html_text) + return html + + +def read_markdown_files() -> Dict[str, str]: + """Read all markdown files from _get_started/additional_platforms directory + and convert them to HTML with syntax highlighting.""" + html_content = {} + + if not MARKDOWN_DIR.exists(): + print(f"Warning: {MARKDOWN_DIR} does not exist") + return html_content + + for md_file in MARKDOWN_DIR.glob("*.md"): + try: + content = md_file.read_text() + # Use filename (without .md) as platform_id + platform_id = md_file.stem + # Convert markdown to HTML with syntax highlighting + html = convert_markdown_to_html(content) + html_content[platform_id] = html + print(f"Loaded and converted markdown: {platform_id} from {md_file.name}") + except Exception as e: + print(f"Error reading {md_file.name}: {e}") + + return html_content + + +def read_template() -> str: + """Read the JS template file.""" + template_path = INCLUDES_DIR / "quick-start-additional-platforms.js" + if not template_path.exists(): + raise FileNotFoundError(f"Template file not found: {template_path}") + return template_path.read_text() + + +def generate_js_output(platform_data: Dict[str, Any], markdown_content: Dict[str, str]) -> str: + """Generate the final JS file by replacing template placeholders.""" + template = read_template() + + # Replace placeholders + template = template.replace("{{ platformData }}", json.dumps(platform_data, indent=2)) + # Now embedding pre-converted HTML content instead of raw markdown + template = template.replace("{{ markdownContent }}", json.dumps(markdown_content, indent=2)) + + return template + + +def write_output(content: str) -> None: + """Write the generated JS to assets directory.""" + output_path = ASSETS_DIR / "quick-start-additional-platforms.js" + output_path.write_text(content) + print(f"Generated: {output_path}") + + +def main(): + """Main entry point.""" + print("Generating additional platforms quick start module...") + + # Read all platform JSON files + platform_data = read_platform_json_files() + + if not platform_data: + print("No platform data found. Creating empty output.") + platform_data = {} + + # Read all markdown files + markdown_content = read_markdown_files() + + if not markdown_content: + print("No markdown content found.") + markdown_content = {} + + # Generate JS output + js_content = generate_js_output(platform_data, markdown_content) + + # Write to assets directory + write_output(js_content) + + print("Done!") + + +if __name__ == "__main__": + main()