-
-
Notifications
You must be signed in to change notification settings - Fork 52
feat: resolution time of procedurally generated functions #2233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
cieplypolar
wants to merge
22
commits into
main
Choose a base branch
from
feat/proc-gen-func
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
63227e3
initial commit
cieplypolar 79f8787
readme by claude
cieplypolar 1aed4d2
Merge branch 'main' into feat/proc-gen-func
cieplypolar b542027
refactor
cieplypolar b124f2b
python + ci
cieplypolar e40fff6
generating charts with mermaid
cieplypolar bc342fa
Merge branch 'main' into feat/proc-gen-func
cieplypolar 4ef79d2
oxfmt
cieplypolar 2c6c86b
Merge branch 'feat/proc-gen-func' of github.com:software-mansion/Type…
cieplypolar 780872b
review fixes
cieplypolar 0e34944
review changes
cieplypolar 861f182
oxfmt
cieplypolar 8129935
readme update
cieplypolar 18c3673
heavy leaf
cieplypolar 5b9ffb7
Merge branch 'main' into feat/proc-gen-func
cieplypolar ad3bb58
random test
cieplypolar bbeddff
Merge branch 'main' into feat/proc-gen-func
cieplypolar 6cd0c5d
refactor
cieplypolar 4a47cb3
review changes
cieplypolar caba1fa
Merge branch 'main' into feat/proc-gen-func
cieplypolar 29e719f
Merge branch 'feat/proc-gen-func' of github.com:software-mansion/Type…
cieplypolar 8ed191f
Merge branch 'main' into feat/proc-gen-func
cieplypolar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # Procedural TypeGPU function generator for benchmarking resolution time | ||
|
|
||
| ## Adding a new instruction | ||
|
|
||
| Each instruction is a `tgpu.comptime` that returns a `tgpu.fn(() => void)`. There are two kinds: **leaf** (no function calls) and **recursive** (branches into other instructions). | ||
|
|
||
| ### Leaf instruction | ||
|
|
||
| ```ts | ||
| const myLeafFn = tgpu.comptime(() => { | ||
| return tgpu.fn(() => { | ||
| 'use gpu'; | ||
| // ... | ||
| popDepth(); // REQUIRED — always call at the end | ||
| }).$name('myLeafFn'); | ||
| }); | ||
| ``` | ||
|
|
||
| ### Recursive instruction | ||
|
|
||
| Use `tgpu.unroll` over `arrayForUnroll(BRANCHING)` and call `instructions[choice()]()()` to branch into other instructions. The `choice()` function handles depth tracking and picks a leaf when at max depth. | ||
|
|
||
| ```ts | ||
| const myRecursiveFn = tgpu.comptime(() => { | ||
| return tgpu.fn(() => { | ||
| 'use gpu'; | ||
| // ... | ||
| for (const _i of tgpu.unroll(arrayForUnroll(BRANCHING))) { | ||
| instructions[choice()]()(); | ||
| } | ||
| popDepth(); // REQUIRED — always call at the end, after the unroll | ||
| }).$name('myRecursiveFn'); | ||
| }); | ||
| ``` | ||
|
|
||
| ## Generating Mermaid charts | ||
|
|
||
| `generateChart.ts` reads benchmark result JSON files and outputs a Mermaid xychart comparing up to 3 datasets. | ||
|
|
||
| ### Usage | ||
|
|
||
| ```sh | ||
| node generateChart.ts \ | ||
| --input "PR:pr-branch/results-max-depth.json" \ | ||
| --input "main:main-branch/results-max-depth.json" \ | ||
| --title "Resolution Time vs Max Depth" \ | ||
| --xAxisTitle "max depth" \ | ||
| --yAxisTitle "time (ms)" \ | ||
| --output chart.md | ||
| ``` | ||
|
|
||
| ### Arguments | ||
|
|
||
| | Argument | Required | Description | | ||
| |---|---|---| | ||
| | `--input <label>:<path>` | yes (1-3) | `label` appears in the legend, `path` points to a benchmark results JSON file generated by `procedural.ts` | | ||
| | `--title <text>` | yes | chart title | | ||
| | `--xAxisTitle <text>` | no | x-axis title | | ||
| | `--yAxisTitle <text>` | no | y-axis title | | ||
| | `--output <path>` | no | write markdown to a file instead of stdout | | ||
|
|
||
| Each `--input` dataset is plotted as a separate line on the same chart. Colors are assigned in order: red, blue, green. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| preload = ["./preload.ts"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| import { readFileSync, writeFileSync } from 'node:fs'; | ||
| import type { BenchmarkResult } from './procedural.ts'; | ||
|
|
||
| interface Dataset { | ||
| label: string; | ||
| data: BenchmarkResult[]; | ||
| } | ||
|
|
||
| const args = process.argv.slice(2); | ||
|
|
||
| const inputs: Dataset[] = []; | ||
| let title = ''; | ||
| let output = ''; | ||
| let xAxisTitle = ''; | ||
| let yAxisTitle = ''; | ||
|
|
||
| // parsing arguments | ||
| for (let i = 0; i < args.length; i++) { | ||
| if (args[i] === '--input') { | ||
| // oxlint-disable-next-line typescript/no-non-null-assertion | ||
| const [label, filepath] = args[++i]!.split(':', 2); | ||
| inputs.push({ | ||
| label: label as string, | ||
| data: JSON.parse(readFileSync(filepath as string, 'utf8')), | ||
| }); | ||
| } else if (args[i] === '--title') { | ||
| if (title !== '') { | ||
| throw new Error('Ambiguous title'); | ||
| } | ||
| // oxlint-disable-next-line typescript/no-non-null-assertion | ||
| title = args[++i]!; | ||
| } else if (args[i] === '--output') { | ||
| if (output !== '') { | ||
| throw new Error('Ambiguous output'); | ||
| } | ||
| // oxlint-disable-next-line typescript/no-non-null-assertion | ||
| output = args[++i]!; | ||
| } else if (args[i] === '--xAxisTitle') { | ||
| if (xAxisTitle !== '') { | ||
| throw new Error('Ambiguous xAxisTitle'); | ||
| } | ||
| // oxlint-disable-next-line typescript/no-non-null-assertion | ||
| xAxisTitle = args[++i]!; | ||
| } else if (args[i] === '--yAxisTitle') { | ||
| if (yAxisTitle !== '') { | ||
| throw new Error('Ambiguous yAxisTitle'); | ||
| } | ||
| // oxlint-disable-next-line typescript/no-non-null-assertion | ||
| yAxisTitle = args[++i]!; | ||
| } | ||
| } | ||
|
|
||
| if (inputs.length === 0) { | ||
| throw new Error('No input path provided'); | ||
| } | ||
|
|
||
| if (inputs.length > 3) { | ||
| throw new Error('Inputs are limited to 3'); | ||
| } | ||
|
|
||
| if (title === '') { | ||
| throw new Error('No title provided'); | ||
| } | ||
|
|
||
| function median(values: number[]): number { | ||
| // oxlint-disable-next-line eslint-plugin-unicorn(no-array-sort) | ||
| const sorted = values.sort((a, b) => a - b); | ||
| const mid = Math.floor(sorted.length / 2); | ||
| // oxlint-disable-next-line typescript/no-non-null-assertion | ||
| return sorted.length % 2 ? sorted[mid]! : (sorted[mid - 1]! + sorted[mid]!) / 2; | ||
| } | ||
|
|
||
| // oxlint-disable-next-line eslint-plugin-unicorn(no-array-sort) | ||
| const allDepths = [...new Set(inputs.flatMap((ds) => ds.data.map((d) => d.maxDepth)))].sort( | ||
| (a, b) => a - b, | ||
| ); | ||
|
|
||
| // mermaid chart | ||
| const lines: string[] = []; | ||
|
|
||
| const symbols = ['\u{1f534}', '\u{1f535}', '\u{1f7e2}']; | ||
| const legend = inputs.map((ds, i) => `${symbols[i]} ${ds.label}`).join(' | '); | ||
|
|
||
| lines.push('```mermaid'); | ||
| lines.push(`--- | ||
| config: | ||
| themeVariables: | ||
| xyChart: | ||
| plotColorPalette: "#E63946, #3B82F6, #059669" | ||
| ---`); | ||
| lines.push('xychart'); | ||
| lines.push(` title "${title} (${legend})"`); | ||
| lines.push(` x-axis "${xAxisTitle ? xAxisTitle : ' '}" [${allDepths.join(', ')}]`); | ||
| lines.push(` y-axis "${yAxisTitle ? yAxisTitle : ' '}"`); | ||
|
|
||
| for (const ds of inputs) { | ||
| const medians = allDepths.map((depth) => { | ||
| const times = ds.data.filter((d) => d.maxDepth === depth).map((d) => d.timeMs); | ||
| return times.length ? median(times).toFixed(2) : '0'; | ||
| }); | ||
| lines.push(` line [${medians.join(', ')}]`); | ||
| } | ||
|
|
||
| lines.push('```'); | ||
|
|
||
| const md = lines.join('\n'); | ||
|
|
||
| if (output) { | ||
| writeFileSync(output, md); | ||
| } else { | ||
| console.log(md); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,17 @@ | ||||||
| { | ||||||
| "name": "resolution-time", | ||||||
| "version": "0.0.0", | ||||||
| "private": true, | ||||||
| "description": "Resolution time benchmark app for TypeGPU", | ||||||
| "type": "module", | ||||||
| "scripts": { | ||||||
| "resolution-time": "bun procedural.ts" | ||||||
| }, | ||||||
| "dependencies": { | ||||||
| "typegpu": "workspace:*" | ||||||
| }, | ||||||
| "devDependencies": { | ||||||
| "bun": "latest", | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's safest to pin a specific version range
Suggested change
|
||||||
| "unplugin-typegpu": "workspace:*" | ||||||
| } | ||||||
| } | ||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import { plugin } from 'bun'; | ||
| import typegpu from 'unplugin-typegpu/bun'; | ||
|
|
||
| void plugin(typegpu({})); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.