Added 863 files from NVIDIA/cccl sparse checkout: - c2h/ (27 files): Catch2 test helpers — generators, validators, runner - nvbench_helper/ (10 files): Benchmark harness utilities - cmake/ (29 files): CMake presets and build helpers - cudax/ (794 files): Experimental CUDA extensions - AGENTS.md: NVIDIA's official AI agent instructions for CCCL - CMakePresets.json: Standardized build configurations - cccl-version.json: Version tracking Also added CCCL_ASSET_MAP.md mapping all 4295 CCCL files to competition value and PRD items. cccl_upstream now covers 100% of competition-critical assets: - 27 tuning headers (SM80/90/100 benchmark data) - 32 dispatch headers (algorithm implementations) - 60 Thrust examples (correctness verification) - 217 CUB Catch2 tests (regression matrix) - 153 CUB benchmarks (parameter space search) - 18 CUB examples (API verification) - 27 test helpers + benchmark harness - 794 cudax experimental extensions
231 lines
8.2 KiB
Python
231 lines
8.2 KiB
Python
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def extract_function_name(template_content):
|
|
"""
|
|
Extract the function name from complex template parameters.
|
|
Examples:
|
|
- 'compute_residual(cuda::experimental::stf::stackable_ctx &, ...' -> 'compute_residual'
|
|
- 'main::[lambda(unsigned long, T1, T2) (instance 1)]' -> 'main'
|
|
"""
|
|
# First, try to find a function-like pattern: name(args...)
|
|
func_match = re.match(r"([a-zA-Z_][a-zA-Z0-9_]*)\s*\(", template_content)
|
|
if func_match:
|
|
return func_match.group(1)
|
|
|
|
# Handle patterns like "main::[lambda...]" - take part before "::"
|
|
if "::" in template_content:
|
|
first_part = template_content.split("::", 1)[0].strip()
|
|
# Extract the identifier
|
|
identifier_match = re.search(r"([a-zA-Z_][a-zA-Z0-9_]*)$", first_part)
|
|
if identifier_match:
|
|
return identifier_match.group(1)
|
|
return first_part
|
|
|
|
# Fallback: take first identifier before comma
|
|
first_part = template_content.split(",", 1)[0].strip()
|
|
|
|
# Extract just the identifier part (remove any type qualifiers)
|
|
identifier_match = re.search(r"([a-zA-Z_][a-zA-Z0-9_]*)$", first_part)
|
|
if identifier_match:
|
|
return identifier_match.group(1)
|
|
|
|
return first_part
|
|
|
|
|
|
def find_matching_bracket(text, start_pos, open_char="<", close_char=">"):
|
|
"""Find the position of the matching closing bracket for nested brackets"""
|
|
bracket_count = 1
|
|
i = start_pos
|
|
while i < len(text) and bracket_count > 0:
|
|
if text[i] == open_char:
|
|
bracket_count += 1
|
|
elif text[i] == close_char:
|
|
bracket_count -= 1
|
|
i += 1
|
|
return i - 1 if bracket_count == 0 else -1
|
|
|
|
|
|
def simplify(line: str) -> str:
|
|
# First, remove the long "void cuda::experimental::stf::reserved::" prefix and variations
|
|
line = line.replace("void cuda::experimental::stf::reserved::", "")
|
|
line = line.replace("cuda::experimental::stf::reserved::", "")
|
|
|
|
# Handle special cases first
|
|
if "loop_redux_finalize" in line:
|
|
line = re.sub(r".*loop_redux_finalize.*", "loop_redux_finalize", line)
|
|
return line
|
|
|
|
# Handle condition_reset - remove angle brackets entirely
|
|
line = re.sub(r"condition_reset<[^>]*>", "condition_reset", line)
|
|
|
|
# Handle loop_redux<...> patterns
|
|
result = line
|
|
pos = 0
|
|
while True:
|
|
match = re.search(r"loop_redux<", result[pos:])
|
|
if not match:
|
|
break
|
|
start = pos + match.start()
|
|
bracket_start = pos + match.end() - 1 # position of '<'
|
|
bracket_end = find_matching_bracket(result, bracket_start + 1)
|
|
if bracket_end != -1:
|
|
inside = result[bracket_start + 1 : bracket_end]
|
|
func_name = extract_function_name(inside)
|
|
# Replace the entire loop_redux<...> with simplified version
|
|
result = (
|
|
result[:start] + f"loop_redux<{func_name}>" + result[bracket_end + 1 :]
|
|
)
|
|
pos = start + len(f"loop_redux<{func_name}>")
|
|
else:
|
|
pos = start + 1
|
|
|
|
# Handle regular loop<...> patterns
|
|
pos = 0
|
|
while True:
|
|
match = re.search(r"loop<", result[pos:])
|
|
if not match:
|
|
break
|
|
start = pos + match.start()
|
|
bracket_start = pos + match.end() - 1 # position of '<'
|
|
bracket_end = find_matching_bracket(result, bracket_start + 1)
|
|
if bracket_end != -1:
|
|
inside = result[bracket_start + 1 : bracket_end]
|
|
func_name = extract_function_name(inside)
|
|
# Replace the entire loop<...> with simplified version
|
|
result = result[:start] + f"loop<{func_name}>" + result[bracket_end + 1 :]
|
|
pos = start + len(f"loop<{func_name}>")
|
|
else:
|
|
pos = start + 1
|
|
|
|
# Handle condition_update_kernel<...> patterns (like loop patterns)
|
|
pos = 0
|
|
while True:
|
|
match = re.search(r"condition_update_kernel<", result[pos:])
|
|
if not match:
|
|
break
|
|
start = pos + match.start()
|
|
bracket_start = pos + match.end() - 1 # position of '<'
|
|
bracket_end = find_matching_bracket(result, bracket_start + 1)
|
|
if bracket_end != -1:
|
|
inside = result[bracket_start + 1 : bracket_end]
|
|
func_name = extract_function_name(inside)
|
|
# Replace the entire condition_update_kernel<...> with simplified version
|
|
result = (
|
|
result[:start]
|
|
+ f"condition_update_kernel<{func_name}>"
|
|
+ result[bracket_end + 1 :]
|
|
)
|
|
pos = start + len(f"condition_update_kernel<{func_name}>")
|
|
else:
|
|
pos = start + 1
|
|
|
|
# Remove function arguments - keep only allowed characters, stop at :: or (
|
|
def clean_after_loop(match):
|
|
loop_part = match.group(1) # the loop<...> or loop_redux<...> part
|
|
after_loop = match.group(2) # everything after it
|
|
|
|
# Keep only letters, underscore, whitespace, and stop at :: or (
|
|
cleaned = ""
|
|
i = 0
|
|
while i < len(after_loop):
|
|
char = after_loop[i]
|
|
if char in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_\t ":
|
|
cleaned += char
|
|
i += 1
|
|
elif i < len(after_loop) - 1 and after_loop[i : i + 2] == "::":
|
|
break # Stop at ::
|
|
elif char == "(":
|
|
break # Stop at (
|
|
elif char == "\n":
|
|
cleaned += char
|
|
break # Stop at newline but include it
|
|
else:
|
|
i += 1 # Skip other characters but keep going
|
|
|
|
return loop_part + cleaned
|
|
|
|
# Apply argument cleanup to loop patterns and condition_update_kernel
|
|
result = re.sub(
|
|
r"((?:loop(?:_redux)?|condition_update_kernel)<[^>]+>)(.*)",
|
|
clean_after_loop,
|
|
result,
|
|
)
|
|
|
|
# Also clean up condition_reset (which has no angle brackets after simplification)
|
|
result = re.sub(r"(condition_reset)(.*)", clean_after_loop, result)
|
|
|
|
return result
|
|
|
|
|
|
def apply_cu_filt(input_text):
|
|
"""Apply cu++filt to demangle C++ symbols"""
|
|
try:
|
|
# Run cu++filt to demangle C++ symbols
|
|
process = subprocess.Popen(
|
|
["cu++filt"],
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
)
|
|
stdout, stderr = process.communicate(input_text)
|
|
|
|
if process.returncode == 0:
|
|
return stdout
|
|
else:
|
|
# If cu++filt fails, fall back to c++filt
|
|
print(f"cu++filt failed: {stderr}, trying c++filt", file=sys.stderr)
|
|
process = subprocess.Popen(
|
|
["c++filt"],
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
)
|
|
stdout, stderr = process.communicate(input_text)
|
|
if process.returncode == 0:
|
|
return stdout
|
|
else:
|
|
print(
|
|
f"c++filt also failed: {stderr}, using original text",
|
|
file=sys.stderr,
|
|
)
|
|
return input_text
|
|
except FileNotFoundError:
|
|
# If cu++filt is not available, try c++filt
|
|
try:
|
|
process = subprocess.Popen(
|
|
["c++filt"],
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
)
|
|
stdout, stderr = process.communicate(input_text)
|
|
if process.returncode == 0:
|
|
return stdout
|
|
else:
|
|
print(f"c++filt failed: {stderr}, using original text", file=sys.stderr)
|
|
return input_text
|
|
except FileNotFoundError:
|
|
print(
|
|
"Neither cu++filt nor c++filt found, using original text",
|
|
file=sys.stderr,
|
|
)
|
|
return input_text
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Read all input
|
|
input_text = sys.stdin.read()
|
|
|
|
# First apply cu++filt to demangle symbols
|
|
demangled_text = apply_cu_filt(input_text)
|
|
|
|
# Then apply our custom simplification to each line
|
|
for line in demangled_text.splitlines(keepends=True):
|
|
print(simplify(line), end="")
|