Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 13 additions & 14 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,19 @@ readme = "README.md"
requires-python = ">=3.9"

# Python dependencies
dependencies = ["tomli", "tabulate", "ml_dtypes", "dspy==2.6.27", "pandas", "duckdb", "rich", "pytest", "litellm[proxy]", "rpds-py"]
dependencies = [
"tomli",
"tabulate",
"ml_dtypes",
"dspy==2.6.27",
"pandas",
"duckdb",
"rich",
"pytest",
"litellm[proxy]",
"rpds-py",
"nexus @ git+https://github.com/AMDResearch/nexus.git@main",
]

[tool.setuptools]
package-dir = {"" = "src"}
Expand All @@ -39,19 +51,6 @@ python3 -m pip install --ignore-installed blinker &&
python3 -m pip install -r requirements.txt
"""


[tool.nexus]
git = "https://github.com/AMDResearch/nexus.git"
branch = "main"
build_command = """
export CC=${ROCM_PATH}/bin/hipcc
export CXX=${ROCM_PATH}/bin/hipcc
cmake -B build -DCMAKE_PREFIX_PATH=/opt/rocm\
-DLLVM_INSTALL_DIR=/opt/rocm/llvm\
-DCMAKE_BUILD_TYPE=Debug
cmake --build build --parallel 16
"""

[project.optional-dependencies]
dev = [
"ruff==0.3.0",
Expand Down
10 changes: 5 additions & 5 deletions src/accordo/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ def __init__(

# Auto-detect accordo_path if not provided
if accordo_path is None:
# Try to find it relative to this file
# Find it relative to this file (accordo package directory)
accordo_dir = Path(__file__).parent
if (accordo_dir / "build").exists() or (accordo_dir / "CMakeLists.txt").exists():
accordo_path = accordo_dir
else:
# Try environment variable
from intelliperf.utils.env import get_accordo_path

accordo_path = Path(get_accordo_path())
raise RuntimeError(
f"Could not find Accordo build directory. Expected at {accordo_dir}. "
"Please build Accordo first or specify accordo_path explicitly."
)

self.accordo_path = Path(accordo_path)
logging.debug(f"Accordo path: {self.accordo_path}")
Expand Down
74 changes: 56 additions & 18 deletions src/intelliperf/core/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
from intelliperf.utils import process
from intelliperf.utils.env import (
get_guided_tuning_path,
get_nexus_path,
get_rocprofiler_path,
)
from intelliperf.utils.process import capture_subprocess_output, exit_on_fail
Expand Down Expand Up @@ -224,26 +223,65 @@ def clone(self):
)

def collect_source_code(self):
nexus_directory = get_nexus_path()
lib = os.path.join(nexus_directory, "build", "lib", "libnexus.so")
env = os.environ.copy()

with tempfile.TemporaryDirectory() as tmp:
json_result_file = os.path.join(tmp, "nexus_output.json")

env["HSA_TOOLS_LIB"] = lib
env["NEXUS_LOG_LEVEL"] = "2"
env["NEXUS_OUTPUT_FILE"] = json_result_file
env["TRITON_ALWAYS_COMPILE"] = "1"
env["TRITON_DISABLE_LINE_INFO"] = "0"
capture_subprocess_output(self.get_app_cmd(), new_env=env, working_directory=self.get_project_directory())

if os.path.exists(json_result_file):
df_results = json.loads(open(json_result_file).read())
"""
Collect source code for GPU kernels using Nexus.

Returns:
dict: Dictionary containing kernel information with assembly, HIP source, files, and line numbers
"""
try:
from nexus import Nexus
except ImportError:
logging.error("Nexus Python API not found. Please install it: pip install git+https://github.com/AMDResearch/nexus.git@main")
return {"kernels": {}}

try:
# Map Python logging level to Nexus log level
# Python: NOTSET=0, DEBUG=10, INFO=20, WARNING=30, ERROR=40, CRITICAL=50
# Nexus: 0=none, 1=info, 2=warning, 3=error, 4=detail
current_level = logging.getLogger().getEffectiveLevel()
if current_level <= logging.DEBUG:
nexus_log_level = 4 # detail (most verbose)
elif current_level <= logging.INFO:
nexus_log_level = 1 # info
elif current_level <= logging.WARNING:
nexus_log_level = 2 # warning
else:
df_results = {"kernels": {}}
nexus_log_level = 0 # none

# Create Nexus tracer with inherited log level
nexus = Nexus(log_level=nexus_log_level)

# Additional environment for Triton kernels
triton_env = {
"TRITON_ALWAYS_COMPILE": "1",
"TRITON_DISABLE_LINE_INFO": "0",
}

# Run the application and capture kernel trace
trace = nexus.run(
command=self.get_app_cmd(),
env=triton_env,
cwd=self.get_project_directory(),
)

# Convert trace to the expected format
df_results = {"kernels": {}}
for kernel in trace:
df_results["kernels"][kernel.name] = {
"assembly": kernel.assembly,
"hip": kernel.hip,
"files": kernel.files,
"lines": kernel.lines,
"signature": kernel.signature,
}

return df_results

except Exception as e:
logging.error(f"Failed to collect source code with Nexus: {e}")
return {"kernels": {}}

def get_binary_absolute_path(self):
if self.get_project_directory() != "":
binary = self.get_app_cmd_without_args()
Expand Down
8 changes: 0 additions & 8 deletions src/intelliperf/utils/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,10 @@ def get_guided_tuning_path():
return (Path(__file__).resolve().parent / "../../../external/guided-tuning").resolve()


def get_accordo_path():
return (Path(__file__).resolve().parent / "../../accordo").resolve()


def get_rocprofiler_path():
return (Path(__file__).resolve().parent / "../../../external/rocprofiler-compute/src").resolve()


def get_nexus_path():
return (Path(__file__).resolve().parent / "../../../external/nexus").resolve()


def get_llm_api_key():
llm_key = os.environ.get("LLM_GATEWAY_KEY")
if not llm_key:
Expand Down
Loading