Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
15 changes: 11 additions & 4 deletions aiter/jit/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

this_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, f"{this_dir}/utils/")
from chip_info import get_gfx
from chip_info import get_gfx, get_gfx_list
from cpp_extension import _jit_compile, get_hip_version
from file_baton import FileBaton
from torch_guard import torch_compile_guard # noqa: E402
Expand Down Expand Up @@ -257,9 +257,16 @@ def get_config_file(env_name, default_file, tuned_file_name):
sys.path.insert(0, AITER_META_DIR)
AITER_CSRC_DIR = f"{AITER_META_DIR}/csrc"
AITER_GRADLIB_DIR = f"{AITER_META_DIR}/gradlib"
gfx = get_gfx()
AITER_ASM_DIR = f"{AITER_META_DIR}/hsa/{gfx}/"
os.environ["AITER_ASM_DIR"] = AITER_ASM_DIR
gfx = get_gfx_list()
if len(gfx) == 1:
# single GPU arch
AITER_ASM_DIR = f"{AITER_META_DIR}/hsa/{gfx[0]}/"
os.environ["AITER_ASM_DIR"] = AITER_ASM_DIR
else:
# multiple GPU archs
AITER_ASM_DIR = [f"{AITER_META_DIR}/hsa/{g}/" for g in gfx]
os.environ["AITER_ASM_DIR"] = ":".join(AITER_ASM_DIR)

CK_3RDPARTY_DIR = os.environ.get(
"CK_DIR", f"{AITER_META_DIR}/3rdparty/composable_kernel"
)
Expand Down
2 changes: 1 addition & 1 deletion aiter/jit/optCompilerConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@
"extra_ldflags": "None",
"extra_include": [],
"verbose": "False",
"blob_gen_cmd": "f'{get_asm_dir()}/bf16gemm/codegen.py --output_dir {{}}'"
"blob_gen_cmd": "f'{AITER_META_DIR}/hsa/codegen.py -m bf16gemm --output_dir {{}}'"
},
"module_gemm_a4w4_asm": {
"srcs": [
Expand Down
7 changes: 6 additions & 1 deletion csrc/py_itfs_cu/asm_gemm_a16w16.cu
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ get_heuristic_kernel(int M,
hipDeviceProp_t dev_prop;
HIP_CALL(hipGetDevice(&dev));
HIP_CALL(hipGetDeviceProperties(&dev_prop, dev));
std::string arch_id = get_gpu_arch();
printf("Arch ID: %s\n", arch_id.c_str());

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Debug printf statement should be removed or guarded by a debug flag before merging to production. Consider using a proper logging mechanism or conditional compilation.

Suggested change
std::string arch_id = get_gpu_arch();
printf("Arch ID: %s\n", arch_id.c_str());
std::string arch_id = get_gpu_arch();
#ifdef DEBUG
printf("Arch ID: %s\n", arch_id.c_str());
#endif

Copilot uses AI. Check for mistakes.
uint32_t num_cu = dev_prop.multiProcessorCount;
// printf("num_cu: %d\n", num_cu);
uint32_t empty_cu = num_cu;
Expand All @@ -75,6 +77,8 @@ get_heuristic_kernel(int M,

for(const auto& el : *cfgs)
{
if (el.first.find(arch_id) != 0)
continue;
const auto& cfg = el.second;
Comment on lines +82 to 84

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The architecture filtering logic assumes that el.first (the kernel name) starts with the architecture ID. This implicit dependency is fragile and not documented. Consider adding a comment explaining this assumption, or better yet, use the cfg.arch field from the configuration struct for explicit architecture matching.

Suggested change
if (el.first.find(arch_id) != 0)
continue;
const auto& cfg = el.second;
const auto& cfg = el.second;
// Explicitly match architecture using cfg.arch instead of relying on kernel name format.
if (cfg.arch != arch_id)
continue;

Copilot uses AI. Check for mistakes.
if(kernelName.has_value() && kernelName.value() != el.first)
continue;
Expand Down Expand Up @@ -125,6 +129,7 @@ get_heuristic_kernel(int M,
compute2mem_effi = local_compute2mem_effi;
oob = (M % cfg.tileM == 0) ? 0 : cfg.tileM - (M % cfg.tileM);
selectedKernelName = el.first;
printf("Selected Kernel: %s\n", selectedKernelName.c_str());

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Debug printf statement should be removed or guarded by a debug flag before merging to production. Consider using a proper logging mechanism or conditional compilation.

Suggested change
selectedKernelName = el.first;
printf("Selected Kernel: %s\n", selectedKernelName.c_str());
selectedKernelName = el.first;
#ifdef DEBUG_ASM_GEMM
printf("Selected Kernel: %s\n", selectedKernelName.c_str());
#endif

Copilot uses AI. Check for mistakes.
selectedsplitK = split_K;
}
}
Expand Down Expand Up @@ -243,7 +248,7 @@ torch::Tensor gemm_a16w16_asm(torch::Tensor& A, // A:[M, K] bf16
if(it_kl != config_map->end())
{
const auto& cfg = it_kl->second;
const char* name = cfg.name.c_str();
const char* name = cfg.knl_name.c_str();
const char* co_name = cfg.co_name.c_str();
SUBM = cfg.tileM;
SUBN = cfg.tileN;
Expand Down
113 changes: 113 additions & 0 deletions hsa/codegen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# SPDX-License-Identifier: MIT
# Copyright (C) 2018-2025, Advanced Micro Devices, Inc. All rights reserved.

import os
import sys

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'sys' is not used.

Suggested change
import sys

Copilot uses AI. Check for mistakes.
import argparse
import glob
import pandas as pd
from collections import defaultdict

this_dir = os.path.dirname(os.path.abspath(__file__))
base_dir = os.path.basename(this_dir)
archs = [os.path.basename(os.path.normpath(path)) for path in os.environ.get("AITER_ASM_DIR").split(":")]

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential AttributeError if AITER_ASM_DIR environment variable is not set. The code will fail with AttributeError: 'NoneType' object has no attribute 'split'. Add a check or provide a default value.

Suggested change
archs = [os.path.basename(os.path.normpath(path)) for path in os.environ.get("AITER_ASM_DIR").split(":")]
archs = [os.path.basename(os.path.normpath(path)) for path in os.environ.get("AITER_ASM_DIR", "").split(":") if path]

Copilot uses AI. Check for mistakes.


content = """// SPDX-License-Identifier: MIT
// Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
#pragma once
#include <unordered_map>

"""

if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="generate",
description="gen API for asm Bf16_gemm kernel",
)
parser.add_argument(
"-m",
"--module",
required=True,
help="""module of ASM kernle

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'kernle' to 'kernel'.

Suggested change
help="""module of ASM kernle
help="""module of ASM kernel

Copilot uses AI. Check for mistakes.
e.g.: -m bf16gemm
""",
)
parser.add_argument(
"-o",
"--output_dir",
default="aiter/jit/build",
required=False,
help="write all the blobs into a directory",
)
args = parser.parse_args()
cfgs = []

csv_groups = defaultdict(list)
for arch in archs:
# print(f"{this_dir}/{arch}/{args.module}")
for el in glob.glob(f"{this_dir}/{arch}/{args.module}/*.csv", recursive=True):
df = pd.read_csv(el)
cfgname = os.path.basename(el).split(".")[0]
csv_groups[cfgname].append({
'file_path': el,
'arch': arch
})

## deal with same name csv
cfgs = []
have_get_header = False
for cfgname, file_info_list in csv_groups.items():
dfs = []
for file_info in file_info_list:
single_file = file_info["file_path"]
arch = file_info['arch']
df = pd.read_csv(single_file)
# check headers
headers_list = df.columns.tolist()
required_columns = {'knl_name', 'co_name'}
if not required_columns.issubset(headers_list):
missing = required_columns - set(headers_list)
print(f"ERROR: Invalid assembly CSV format -- {single_file}. Missing required columns: {', '.join(missing)}")

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error is printed but execution continues, which may lead to downstream failures. The script should exit with a non-zero status code after printing the error using sys.exit(1) to prevent generating invalid configurations.

Suggested change
print(f"ERROR: Invalid assembly CSV format -- {single_file}. Missing required columns: {', '.join(missing)}")
print(f"ERROR: Invalid assembly CSV format -- {single_file}. Missing required columns: {', '.join(missing)}")
sys.exit(1)

Copilot uses AI. Check for mistakes.
df['arch'] = arch # add arch into df
dfs.append(df)
if dfs:
combine_df = pd.concat(dfs, ignore_index=True).fillna(0)
if have_get_header == False:

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Use if not have_get_header: instead of if have_get_header == False: for more Pythonic code.

Suggested change
if have_get_header == False:
if not have_get_header:

Copilot uses AI. Check for mistakes.
headers_list = combine_df.columns.tolist()
required_columns = {'knl_name', 'co_name', 'arch'}
other_columns = [col for col in headers_list if col not in required_columns]
other_columns_comma = ', '.join(other_columns)
other_columns_cpp_def = "\n".join([f" int {col};" for col in other_columns])
content += f'''
#define ADD_CFG({other_columns_comma}, path, knl_name, co_name, arch) \\
{{ \\
arch knl_name, {{ knl_name, path co_name, arch, {other_columns_comma} }} \\

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing string concatenation operator between path and co_name. This will result in a C++ syntax error. Should be path \" \" co_name or path + co_name depending on the intended behavior.

Suggested change
arch knl_name, {{ knl_name, path co_name, arch, {other_columns_comma} }} \\
arch knl_name, {{ knl_name, path + co_name, arch, {other_columns_comma} }} \\

Copilot uses AI. Check for mistakes.
}}

struct {args.module}Config
{{
std::string knl_name;
std::string co_name;
std::string arch;
{other_columns_cpp_def}
}};

using CFG = std::unordered_map<std::string, {args.module}Config>;

'''
have_get_header = True
cfg = [
f'ADD_CFG({", ".join(str(getattr(row, col)) for col in other_columns)}, "{os.path.relpath(os.path.dirname(el), f"{this_dir}/{arch}")}/", "{row.knl_name}", "{row.co_name}", "{row.arch}"),'

Copilot AI Nov 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable el is used from the outer loop but this code is inside a loop iterating over file_info_list. The variable el refers to the last CSV file from the outer loop (line 49), not the current file. This will generate incorrect paths. Should use single_file or track the file path correctly.

Copilot uses AI. Check for mistakes.
for row in combine_df.itertuples(index=False)
]
cfg_txt = "\n ".join(cfg) + "\n"

txt = f"""static CFG cfg_{cfgname} = {{
{cfg_txt}}};"""
cfgs.append(txt)

content += "\n".join(cfgs) + "\n"

with open(f"{args.output_dir}/asm_{args.module}_configs.hpp", "w") as f:
f.write(content)
2 changes: 1 addition & 1 deletion hsa/gfx942/bf16gemm/bf16gemm_outf32.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
knl_name,knl_file,tn,tileM,tileN,pf
knl_name,co_name,tn,tileM,tileN,pf
_ZN5aiter28bf16gemm_outf32_tn_32x64_pf3E,bf16gemm_outf32_tn_32x64_pf3.co,1,32,64,3
_ZN5aiter28bf16gemm_outf32_tn_48x64_pf3E,bf16gemm_outf32_tn_48x64_pf3.co,1,48,64,3
_ZN5aiter28bf16gemm_outf32_tn_64x64_pf3E,bf16gemm_outf32_tn_64x64_pf3.co,1,64,64,3
Expand Down
2 changes: 1 addition & 1 deletion hsa/gfx950/bf16gemm/bf16gemm_outf32.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
knl_name,knl_file,tn,tileM,tileN,pf
knl_name,co_name,tn,tileM,tileN,pf
_ZN5aiter28bf16gemm_outf32_tn_32x64_pf3E,bf16gemm_outf32_tn_32x64_pf3.co,1,32,64,3
_ZN5aiter28bf16gemm_outf32_tn_48x64_pf3E,bf16gemm_outf32_tn_48x64_pf3.co,1,48,64,3
_ZN5aiter28bf16gemm_outf32_tn_64x64_pf3E,bf16gemm_outf32_tn_64x64_pf3.co,1,64,64,3
Expand Down
Loading