mirror of
https://github.com/ROCm/composable_kernel.git
synced 2026-06-30 19:57:40 +00:00
Script to convert MIOpenDriver commands to CK profiler input.
This commit is contained in:
221
script/convert_miopen_driver_commands.py
Executable file
221
script/convert_miopen_driver_commands.py
Executable file
@@ -0,0 +1,221 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import os
|
||||
|
||||
def parse_miopen_command(miopen_cmd):
|
||||
"""Parse MIOpen driver command and extract parameters"""
|
||||
# Remove 'convbfp16' or similar prefix and split into arguments
|
||||
parts = miopen_cmd.strip().split()
|
||||
if not parts:
|
||||
return None
|
||||
|
||||
# Skip the command name (convbfp16, convfp16, etc.)
|
||||
args = parts[1:] if parts[0].startswith('conv') else parts
|
||||
|
||||
params = {}
|
||||
i = 0
|
||||
while i < len(args):
|
||||
if args[i].startswith('-'):
|
||||
key = args[i]
|
||||
if i + 1 < len(args) and not args[i + 1].startswith('-'):
|
||||
params[key] = args[i + 1]
|
||||
i += 2
|
||||
else:
|
||||
params[key] = True
|
||||
i += 1
|
||||
else:
|
||||
i += 1
|
||||
|
||||
return params
|
||||
|
||||
def determine_operation_type(params):
|
||||
"""Determine the operation type based on MIOpen parameters"""
|
||||
# TODO: Current data is for bwd weight.
|
||||
return "grouped_conv_bwd_weight"
|
||||
|
||||
def convert_miopen_to_ck_profiler(miopen_cmd):
|
||||
"""Convert MIOpen driver command to CK profiler command"""
|
||||
params = parse_miopen_command(miopen_cmd)
|
||||
if not params:
|
||||
return None
|
||||
|
||||
# Determine operation type
|
||||
operation = determine_operation_type(params)
|
||||
|
||||
data_type = 5 # BF16
|
||||
layout = 2 # channels last
|
||||
verification = 1 # with verification
|
||||
init_method = 2 # uniform data
|
||||
print_output = 0 # no print output
|
||||
time_kernel = 1 # time kernel
|
||||
n_dim = 2 # 2D convolution by default
|
||||
|
||||
# Build CK profiler command
|
||||
ck_cmd = [operation, str(data_type), str(layout), str(verification),
|
||||
str(init_method), str(print_output), str(time_kernel), str(n_dim)]
|
||||
|
||||
# Add tensor dimensions
|
||||
G = params.get('-g', '1')
|
||||
N = params.get('-n', '1')
|
||||
K = params.get('-k', '1')
|
||||
C = params.get('-c', '1')
|
||||
|
||||
ck_cmd.extend([G, N, K, C])
|
||||
|
||||
Y = params.get('-y', '1')
|
||||
X = params.get('-x', '1')
|
||||
ck_cmd.extend([Y, X])
|
||||
|
||||
# Input dimensions
|
||||
Hi = params.get('-H', '1')
|
||||
Wi = params.get('-W', '1')
|
||||
ck_cmd.extend([Hi, Wi])
|
||||
|
||||
# Stride
|
||||
stride_h = params.get('-u', '1')
|
||||
stride_w = params.get('-v', '1')
|
||||
ck_cmd.extend([stride_h, stride_w])
|
||||
|
||||
# Dilation
|
||||
dilation_h = params.get('-l', '1')
|
||||
dilation_w = params.get('-j', '1')
|
||||
ck_cmd.extend([dilation_h, dilation_w])
|
||||
|
||||
# Padding
|
||||
pad_h = params.get('-p', '0')
|
||||
pad_w = params.get('-q', '0')
|
||||
ck_cmd.extend([pad_h, pad_w, pad_h, pad_w]) # Assuming symmetric padding
|
||||
|
||||
# Split-K
|
||||
split_k = "all"
|
||||
ck_cmd.append(split_k)
|
||||
|
||||
return ' '.join(ck_cmd)
|
||||
|
||||
def convert_file(input_file, output_file):
|
||||
"""Convert MIOpen commands from input file and save CK profiler commands to output file"""
|
||||
converted_commands = []
|
||||
failed_conversions = []
|
||||
|
||||
try:
|
||||
with open(input_file, 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
# Skip header line if present
|
||||
start_idx = 0
|
||||
if lines and (lines[0].strip().lower() == 'shape' or 'conv' not in lines[0].lower()):
|
||||
start_idx = 1
|
||||
|
||||
for line_num, line in enumerate(lines[start_idx:], start_idx + 1):
|
||||
line = line.strip()
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
|
||||
ck_cmd = convert_miopen_to_ck_profiler(line)
|
||||
if ck_cmd:
|
||||
converted_commands.append(ck_cmd)
|
||||
else:
|
||||
failed_conversions.append((line_num, line))
|
||||
|
||||
# Write converted commands to output file
|
||||
with open(output_file, 'w') as f:
|
||||
for cmd in converted_commands:
|
||||
f.write(cmd + '\n')
|
||||
|
||||
print(f"Conversion completed successfully!")
|
||||
print(f"Input file: {input_file}")
|
||||
print(f"Output file: {output_file}")
|
||||
print(f"Converted {len(converted_commands)} commands")
|
||||
|
||||
if failed_conversions:
|
||||
print(f"\nFailed to convert {len(failed_conversions)} commands:")
|
||||
for line_num, line in failed_conversions[:5]: # Show first 5 failures
|
||||
print(f" Line {line_num}: {line[:80]}...")
|
||||
if len(failed_conversions) > 5:
|
||||
print(f" ... and {len(failed_conversions) - 5} more")
|
||||
|
||||
return True
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: Input file '{input_file}' not found")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Error during conversion: {e}")
|
||||
return False
|
||||
|
||||
def generate_output_filename(input_file):
|
||||
"""Generate output filename based on input filename"""
|
||||
base_name = os.path.splitext(input_file)[0]
|
||||
return f"{base_name}_ck_profiler.txt"
|
||||
|
||||
def parse_arguments():
|
||||
"""Parse command line arguments"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Convert MIOpen driver commands to CK profiler commands',
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""Examples:
|
||||
python3 convert_miopen_driver_to_profiler.py miopen_commands.txt
|
||||
python3 convert_miopen_driver_to_profiler.py miopen_commands.txt -o ck_commands.txt
|
||||
python3 convert_miopen_driver_to_profiler.py --validate miopen_commands.txt"""
|
||||
)
|
||||
|
||||
parser.add_argument('input_file',
|
||||
help='Input file containing MIOpen driver commands')
|
||||
parser.add_argument('-o', '--output',
|
||||
help='Output file for CK profiler commands (default: auto-generated)')
|
||||
parser.add_argument('--validate', action='store_true',
|
||||
help='Validate converted commands (dry run)')
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def main():
|
||||
args = parse_arguments()
|
||||
|
||||
# Check if input file exists
|
||||
if not os.path.exists(args.input_file):
|
||||
print(f"Error: Input file '{args.input_file}' does not exist")
|
||||
sys.exit(1)
|
||||
|
||||
# Generate output filename if not provided
|
||||
output_file = args.output if args.output else generate_output_filename(args.input_file)
|
||||
|
||||
# Validate mode - just show what would be converted
|
||||
if args.validate:
|
||||
print("Validation mode - showing first 5 conversions:")
|
||||
try:
|
||||
with open(args.input_file, 'r') as f:
|
||||
lines = f.readlines()[:6] # Header + 5 commands
|
||||
|
||||
start_idx = 1 if lines and 'conv' not in lines[0].lower() else 0
|
||||
|
||||
for i, line in enumerate(lines[start_idx:start_idx+5]):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
ck_cmd = convert_miopen_to_ck_profiler(line)
|
||||
print(f"\n{i+1}. MIOpen: {line[:80]}{'...' if len(line) > 80 else ''}")
|
||||
print(f" CK: {ck_cmd if ck_cmd else 'CONVERSION FAILED'}")
|
||||
|
||||
print(f"\nWould write to: {output_file}")
|
||||
except Exception as e:
|
||||
print(f"Validation error: {e}")
|
||||
|
||||
return
|
||||
|
||||
# Perform the actual conversion
|
||||
success = convert_file(args.input_file, output_file)
|
||||
|
||||
if success:
|
||||
print(f"\nConversion completed! You can now use the converted commands with:")
|
||||
print(f" # For individual command testing:")
|
||||
print(f" ./profiler/ck_tile/ckTileProfiler <command_from_{os.path.basename(output_file)}>")
|
||||
print(f" ")
|
||||
print(f" # For batch processing, you can create a script that reads from {os.path.basename(output_file)}")
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user