blob: 3092cd86623677d1babd76ab30c9b73214e752e7 [file] [log] [blame]
import argparse
from library import *
from matmul import *
from manifest import *
from performance_report import *
###############################################################################
# Map of operation kinds to their dispatch launchers.
operation_launcher_map = {
OperationKind.Matmul: MatmulOperationLauncher,
}
###############################################################################
###############################################################################
# Profiler main : The main entry point for the profiler tool.
###############################################################################
# This tool compiles, verifies, and profiles IREE-compiled MLIR operations for
# a given backend device, compiler flags, and tuning configuration.
#
# The dispatch profiler tool is organized based on below defintions:
# Operation: A MLIR operation that is generated or consumed by the
# dispatch_profiler. For example, linalg.matmul, linalg.conv2d, etc.
# Configuration: A set of compile parameters that are used by iree-compile the
# to choose a compilation pipeline (e.g. LLVMGPUTensorCore,
# LLVMGPUTensorCoreMmaSync, LLVGPUCPU, etc.), performance tuning parameters
# (e.g. workgroup size, tile size etc.).
# Dispatch: A combination of an operation and a configuration is launched by the
# dispatch profiler for verification and performance profiling. Note that
# a dispatch is not a MLIR operation it is binary executable that is launched
# by the profiler. Additionaly, the goal of the tool is to also profile the
# performance of the fusions and a dispatch for fusion is a combination of
# multiple operations glued together and compiled into a single dispatch.
###############################################################################
if __name__ == "__main__":
###############################################################################
# Parse command line arguments
###############################################################################
parser = argparse.ArgumentParser(description="IREE Python profiler tool for "\
"verifcation and performance profiling tool "\
"for IREE-compiled MLIR operations.")
###############################################################################
# General profiler options
parser.add_argument("--build-dir", default=".", \
help="IREE top-level build directory is used to generate "\
"operations and npy files.This should be same that used "\
"to call generated.py")
parser.add_argument("--operation_kind", default="all", help="Specifies the "\
"operation kinds to generate.", choices=["matmul", "conv2d", "all"])
parser.add_argument("--verbose", default='False', \
help='Prints verbose output and commands executed.')
# Generator-specific options
parser.add_argument("--dispatches", default='', help="Comma delimited list to "\
"filter dispatches by name. A dispatch is a combination of "\
"operation and tuning configuration.")
parser.add_argument("--mlir-dialect", default='linalg', help="MLIR dialect entry "\
"point at which operation is emitter.",
choices=["linalg", "flow", "all"])
# Compilation-specific options
parser.add_argument("--device", default="cuda", \
help="Target backend device to benchmark the operation on. "\
"For example, cuda, vulkan, etc.")
parser.add_argument("--force-compile", default='False', \
type=str, help="Force re-compilation of the operation even "\
"if .vmfb file is present.")
parser.add_argument("--compile-only", default='False', \
type=str, help="Compiles the operation "\
"without running verification and profiling.")
# Profiling-specific options
parser.add_argument("--profiling-enabled", "--benchmark", default='True', \
type=str, help="Benchmark the operation.")
parser.add_argument('--batch-size', '--benchmark-dispatch-repeat-count', \
default=100, help="Number of times dispatch is launched "\
"in a loop to amortize the launch overhead.")
parser.add_argument("--benchmark-repetitions", default=5,
type=int, help="Number of times benchmark is repeated "\
"and min, max, median, and average runtimes/gflops are "\
"reported.")
# Verification-specific options
parser.add_argument("--verification-enabled", default='True',
type=str, help="Verify the operation against reference numpy "\
"implementation.")
# Performance reporting options
parser.add_argument("--output", default='', \
help="Path to output file for csv readable results.")
parser.add_argument("--append", default='false', \
help="If true, result is appended to possibly existing file. "\
"Otherwise, any existing file is overwritten.")
parser.add_argument("--tags", default='', \
help="Inserts leading columns in output table and uniform "\
"values for each column. Useful for generating pivot tables.")
# Parse the command line arguments.
args = parser.parse_args()
###############################################################################
# Boolenize the string arguments from command line.
verification_enabled = False if args.verification_enabled in [
'False', 'false', '0'
] else True
profiling_enabled = False if args.profiling_enabled in [
'False', 'false', '0'
] else True
compile_only = False if args.compile_only in ['False', 'false', '0'] else True
# Overrite verification and profiling if compile_only is set.
if compile_only:
verification_enabled = False
profiling_enabled = False
# Manifests metadata for a group of accompanying operations and configurations.
manifest = Manifest(args)
# Load all the pre-defined dispatches in a manifest.
manifest.load()
# Performance report
perf_report = PerformanceReport(args)
# For all the operations in the manifest compile, verify, and profile.
for operation_kind, operation_collection_list in manifest.operations.items():
for operation_collection in operation_collection_list:
# Select and create an instance of operation_launcher for the operation with operation_kind.
# print(operation_collection.operation.name())
operation_launcher = operation_launcher_map[operation_kind](
args, operation_collection.operation)
for configuration in operation_collection.configuration_list:
# Compile the operation dispatches for verification and profiling.
if compile_only:
operation_launcher.compile(CompilationMode.Verify)
operation_launcher.compile(CompilationMode.Profile)
else:
# Initialize verification and profiling results.
verification_result = 'Not verified' if not verification_enabled else 'Failed'
runtime = -1.0
# Launch the operation dispatches for verification and profiling.
if verification_enabled:
verification_result = operation_launcher.verify(configuration)
if profiling_enabled:
runtime = operation_launcher.profile(configuration)
# Save and print the performance result.
if verification_enabled or profiling_enabled:
# Create and print a performance result.
result = PerformanceResult(operation_collection.operation,
configuration, verification_result,
runtime)
result.print()
# Append the performance result to the performance report.
perf_report.append_perf_result(result)