Skip to content

Commit d9dbe15

Browse files
committed
Add check_godbolt.py script to auto-generate godbolt links
1 parent ae3ac6e commit d9dbe15

File tree

2 files changed

+172
-15
lines changed

2 files changed

+172
-15
lines changed

README.md

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -204,28 +204,28 @@ We plan to add many GPU-accelerated, concurrent data structures to `cuCollection
204204
`cuco::static_set` is a fixed-size container that stores unique elements in no particular order. See the Doxygen documentation in `static_set.cuh` for more detailed information.
205205

206206
#### Examples:
207-
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/96re4zhjo))
208-
- [Device-ref APIs for individual operations](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/device_ref_example.cu) (see [live example in godbolt](https://godbolt.org/z/7aKWdGTfx))
209-
- [One single storage for multiple sets](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/device_subsets_example.cu) (see [live example in godbolt](https://godbolt.org/z/7f9KW44P4))
210-
- [Using shared memory as storage](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/shared_memory_example.cu) (see [live example in godbolt](https://godbolt.org/z/Ws5c71T4z))
211-
- [Using set as mapping table to handle large keys or indeterministic sentinels](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/mapping_table_example.cu) (see [live example in godbolt](https://godbolt.org/z/KfYo4nMss))
207+
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/5j5Y5bdE4))
208+
- [Device-ref APIs for individual operations](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/device_ref_example.cu) (see [live example in godbolt](https://godbolt.org/z/M3G9eosa8))
209+
- [One single storage for multiple sets](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/device_subsets_example.cu) (see [live example in godbolt](https://godbolt.org/z/bjbMY1sfa))
210+
- [Using shared memory as storage](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/shared_memory_example.cu) (see [live example in godbolt](https://godbolt.org/z/7qMvd1bhY))
211+
- [Using set as mapping table to handle large keys or indeterministic sentinels](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_set/mapping_table_example.cu) (see [live example in godbolt](https://godbolt.org/z/feqe5dY46))
212212

213213
### `static_map`
214214

215215
`cuco::static_map` is a fixed-size hash table using open addressing with linear probing. See the Doxygen documentation in `static_map.cuh` for more detailed information.
216216

217217
#### Examples:
218-
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_map/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/ndccPsj11))
219-
- [Device-ref APIs for individual operations](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_map/device_ref_example.cu) (see [live example in godbolt](https://godbolt.org/z/e9j5o6f5M))
220-
- [Custom data types, key equality operators and hash functions](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_map/custom_type_example.cu) (see [live example in godbolt](https://godbolt.org/z/xx74Knn3r))
221-
- [Key histogram](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_map/count_by_key_example.cu) (see [live example in godbolt](https://godbolt.org/z/fz7q1vav6))
218+
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_map/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/58bW3h5qf))
219+
- [Device-ref APIs for individual operations](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_map/device_ref_example.cu) (see [live example in godbolt](https://godbolt.org/z/e7KhPj4vh))
220+
- [Custom data types, key equality operators and hash functions](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_map/custom_type_example.cu) (see [live example in godbolt](https://godbolt.org/z/6jbahv1P1))
221+
- [Key histogram](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_map/count_by_key_example.cu) (see [live example in godbolt](https://godbolt.org/z/8jx19v53Y))
222222

223223
### `static_multimap`
224224

225225
`cuco::static_multimap` is a fixed-size hash table that supports storing equivalent keys. It uses double hashing by default and supports switching to linear probing. See the Doxygen documentation in `static_multimap.cuh` for more detailed information.
226226

227227
#### Examples:
228-
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_multimap/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/aq8jz8G9e))
228+
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/static_multimap/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/jYT7cY7xj))
229229

230230
### `dynamic_map`
231231

@@ -239,14 +239,12 @@ We plan to add many GPU-accelerated, concurrent data structures to `cuCollection
239239
`cuco::hyperloglog` implements the well-established [HyperLogLog++ algorithm](https://static.googleusercontent.com/media/research.google.com/de//pubs/archive/40671.pdf) for approximating the count of distinct items in a multiset/stream.
240240

241241
#### Examples:
242-
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/hyperloglog/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/G4qdcTezE))
243-
- [Device-ref APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/hyperloglog/device_ref_example.cu) (see [live example in godbolt](https://godbolt.org/z/n88713o4n))
242+
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/hyperloglog/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/YY31je7YE))
243+
- [Device-ref APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/hyperloglog/device_ref_example.cu) (see [live example in godbolt](https://godbolt.org/z/qjjYjjzco))
244244

245245
### `bloom_filter`
246246

247247
`cuco::bloom_filter` implements a Blocked Bloom Filter for approximate set membership queries.
248248

249249
#### Examples:
250-
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/bloom_filter/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/EY7T5v5aE))
251-
252-
250+
- [Host-bulk APIs](https://github.com/NVIDIA/cuCollections/blob/dev/examples/bloom_filter/host_bulk_example.cu) (see [live example in godbolt](https://godbolt.org/z/YbrcxMffe))

ci/check_godbolt.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
#!/usr/bin/env python
2+
3+
import os
4+
import json
5+
import requests
6+
import git
7+
import re
8+
import argparse
9+
10+
def open_file(file_path):
11+
with open(file_path, 'r') as file:
12+
data = file.read()
13+
return data
14+
15+
def write_file(file_path, data):
16+
with open(file_path, 'w') as file:
17+
file.write(data)
18+
19+
def create_compiler_explorer_shortlink(file_path, COMPILER_ID, COMPILER_FLAGS):
20+
source_code = open_file(file_path)
21+
# Step 1: Prepare the JSON payload
22+
payload = {
23+
"sessions": [
24+
{
25+
"id": 1,
26+
"language": "cuda",
27+
"source": source_code,
28+
"compilers": [
29+
{
30+
"id": COMPILER_ID,
31+
"options": COMPILER_FLAGS,
32+
"libs": [
33+
{
34+
"id": "cccl",
35+
"version": "trunk"
36+
},
37+
{
38+
"id": "cuco",
39+
"version": "dev"
40+
}
41+
]
42+
}
43+
]
44+
}
45+
]
46+
}
47+
48+
# Step 2: Send a POST request to the /api/shortener endpoint
49+
url = 'https://godbolt.org/api/shortener'
50+
headers = {'Content-Type': 'application/json'}
51+
52+
response = requests.post(url, headers=headers, data=json.dumps(payload))
53+
54+
# Step 3: Parse the response
55+
if response.status_code == 200:
56+
data = response.json()
57+
short_url = data.get('url')
58+
if short_url:
59+
return short_url
60+
else:
61+
print("Error: Short URL not found in response.")
62+
return None
63+
else:
64+
print(f"Error: Request failed with status code {response.status_code}")
65+
print(f"Response: {response.text}")
66+
return None
67+
68+
def update_readme_with_shortlinks(readme_path, shortlink_table):
69+
# Open and read the README.md file
70+
readme_content = open_file(readme_path)
71+
lines = readme_content.splitlines()
72+
73+
updated_lines = []
74+
# Iterate through each line of the README
75+
for line in lines:
76+
updated_line = line
77+
# Check each file in the shortlink_table
78+
for file_name, shortlink in shortlink_table.items():
79+
# Check if the file name exists in the line
80+
if file_name in line:
81+
# Look for the specific godbolt link format and replace the URL
82+
updated_line = re.sub(
83+
r"\(see \[live example in godbolt\]\(https?://[^\)]+\)\)",
84+
f"(see [live example in godbolt]({shortlink}))",
85+
line
86+
)
87+
updated_lines.append(updated_line)
88+
89+
# Join the lines and write the updated content back to README.md
90+
updated_content = "\n".join(updated_lines)
91+
write_file(readme_path, updated_content)
92+
93+
COMPILER_ID = 'nvcc125u1' # Desired compiler ID
94+
COMPILER_FLAGS = '-std=c++17 -arch=sm_70 --expt-extended-lambda' # NVCC compiler flags
95+
EXAMPLES_DIR = "examples" # Path to the examples directory relative to the repo root
96+
97+
def main():
98+
# Parse command-line arguments
99+
parser = argparse.ArgumentParser(description="Generate shortlinks for example CUDA files.")
100+
parser.add_argument('--force', action='store_true', help="Generate new links for all example files, even if unchanged.")
101+
args = parser.parse_args()
102+
103+
# Initialize the Git repository
104+
repo = git.Repo(search_parent_directories=True)
105+
repo_root = repo.git.rev_parse("--show-toplevel")
106+
107+
# Ensure we are in the ci directory
108+
ci_dir = os.path.join(repo_root, 'ci')
109+
os.chdir(ci_dir)
110+
111+
# Check if the remote repository already exists
112+
try:
113+
remote = repo.remote("gold_cuco")
114+
except git.exc.NoSuchRemoteError:
115+
# Create the remote repository if it doesn't exist
116+
remote = repo.create_remote("gold_cuco", "https://github.com/NVIDIA/cuCollections.git")
117+
print("Remote 'gold_cuco' created.")
118+
119+
# Fetch the remote repository
120+
print("Fetching latest changes from the remote 'gold_cuco'...")
121+
remote.fetch()
122+
123+
# Get the current branch
124+
current_branch = repo.active_branch
125+
126+
# Get the 'dev' branch from the remote
127+
dev_branch = remote.refs.dev
128+
129+
# Initialize a hash table (dictionary) to store file shortlinks
130+
shortlink_table = {}
131+
132+
# Determine which files to process based on the --force flag
133+
if args.force:
134+
# Get all .cu and .cuh files in the examples directory
135+
example_files = []
136+
for root, _, files in os.walk(os.path.join(repo_root, EXAMPLES_DIR)):
137+
for file_name in files:
138+
if file_name.endswith('.cu') or file_name.endswith('.cuh'):
139+
example_files.append(os.path.relpath(os.path.join(root, file_name), repo_root))
140+
else:
141+
# Get the list of changed files between the current branch and the 'dev' branch
142+
changed_files = current_branch.commit.diff(dev_branch.commit)
143+
example_files = [diff.b_path for diff in changed_files if diff.b_path.startswith(EXAMPLES_DIR) and (diff.b_path.endswith('.cu') or diff.b_path.endswith('.cuh'))]
144+
145+
# Iterate through the example files and create short links
146+
for file_path in example_files:
147+
full_file_path = os.path.join(repo_root, file_path)
148+
shortlink = create_compiler_explorer_shortlink(full_file_path, COMPILER_ID, COMPILER_FLAGS)
149+
if shortlink:
150+
shortlink_table[file_path] = shortlink # Store the file and its shortlink in the hash table
151+
print(f"File: {file_path}: Shortlink: {shortlink}")
152+
153+
# Update README.md with the shortlinks
154+
readme_path = os.path.join(repo_root, "README.md")
155+
update_readme_with_shortlinks(readme_path, shortlink_table)
156+
157+
if __name__ == "__main__":
158+
main()
159+

0 commit comments

Comments
 (0)