Skip to content

Hikettei/ir#14

Closed
hikettei wants to merge 10 commits intomainfrom
hikettei/ir
Closed

Hikettei/ir#14
hikettei wants to merge 10 commits intomainfrom
hikettei/ir

Conversation

@hikettei
Copy link
Owner

No description provided.

@github-actions
Copy link

🤖 Hi @hikettei, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@gemini-code-assist
Copy link

Summary of Changes

Hello @hikettei, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request fundamentally refactors the compiler's core, introducing a robust framework for defining and optimizing tensor computations. It establishes a new Intermediate Representation (IR) and integrates a polyhedral model for advanced loop transformations, enabling efficient code generation for various targets. The changes provide a powerful and flexible foundation for future compiler development.

Highlights

  • New Intermediate Representation (IR): Introduced a new RISC-style IR defined in caten/ops.py with distinct operation categories (Unary, Binary, Ternary, Memory, Control, Meta Ops) and a Node class for graph representation. This includes UPat and PatternMatcher for graph transformations.
  • Frontend DSL and Tracing Mechanism: Implemented a Pythonic Domain-Specific Language (DSL) for defining tensor computations. This involves new caten/kernel.py for kernel definition, symbolic variables, loop directives (parallel, vectorize, unroll), and control flow (range, when). caten/tensor.py defines the Tensor object that proxies operations to IR nodes, and caten/trace.py provides a GraphBuilder for capturing the computation graph via symbolic execution.
  • Polyhedral Model Integration: Deepened integration with the ISL (Integer Set Library) polyhedral model. New files in caten/polyhedral/ define Scop, Computation, PolyhedralSchedule, ASTVisitor, and AstToGraphConverter. This allows for building an ISL schedule from the Caten IR graph and converting the optimized ISL AST back into a Caten IR graph for code generation.
  • Runtime and C Code Generation: Added abstract Runtime and CompiledKernel interfaces in caten/runtime.py. A concrete ClangRuntime and ClangRenderer in caten/runtimes/clang.py are introduced to compile the Caten IR graph into C code, including support for loop pragmas (e.g., OpenMP, Clang loop directives).
  • Updated Documentation and Examples: The docs/IR_AND_DESIGN.md has been completely rewritten to reflect the new architecture. New examples (examples/directives.py, examples/e2e_matmul.py) and tests (test/test_control_flow.py, test/test_pattern_matcher.py) demonstrate the new DSL features and IR capabilities.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

🤖 I'm sorry @hikettei, but I was unable to process your request. Please see the logs for more details.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a significant and well-designed infrastructure for a new frontend DSL and IR, including tracing, a pattern matcher, and integration with a polyhedral backend. This is a solid foundation for the project. My review focuses on a critical thread-safety issue in the tracing mechanism, a few functional gaps between the frontend API and the backend implementation, and several opportunities for improving maintainability and performance.

def unroll(factor: int = 4) -> Directive: return Directive("unroll", (factor,))

# --- Range ---
_range_counter = 0

Choose a reason for hiding this comment

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

critical

The global _range_counter is not thread-safe. If two kernels are traced in parallel threads, they will share and modify this counter, leading to a race condition. This should be moved into the GraphBuilder class in caten/trace.py to make it thread-local. This is the first of several changes to address this.

Comment on lines +43 to +47
global _range_counter
self.args = args
self.iter_sym = Symbol(f"i{_range_counter}")
self.directives: List[Directive] = []
_range_counter += 1

Choose a reason for hiding this comment

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

critical

To fix the thread-safety issue with _range_counter, this logic should be updated to use a counter from the GraphBuilder instance instead of a global variable. This change depends on adding range_counter to the GraphBuilder class.

Suggested change
global _range_counter
self.args = args
self.iter_sym = Symbol(f"i{_range_counter}")
self.directives: List[Directive] = []
_range_counter += 1
builder = get_builder()
self.args = args
self.iter_sym = Symbol(f"i{builder.range_counter}")
self.directives: List[Directive] = []
builder.range_counter += 1

Comment on lines +120 to +121
global _range_counter
_range_counter = 0

Choose a reason for hiding this comment

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

critical

As part of making the range counter thread-safe, this global reset should be removed. The counter should be part of GraphBuilder and reset in GraphBuilder.reset().

Comment on lines +9 to +16
class GraphBuilder:
def __init__(self) -> None:
# The root block of the graph
self.root_block: List[Node] = []
# Stack of active blocks (lists of nodes) where new nodes are appended
self.block_stack: List[List[Node]] = [self.root_block]
# Inputs to the kernel
self.inputs: List[Node] = []

Choose a reason for hiding this comment

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

critical

To fix a thread-safety issue with loop variable naming, a counter for ranges should be stored here in GraphBuilder instead of as a global variable. This makes the counter thread-local via contextvars.

Suggested change
class GraphBuilder:
def __init__(self) -> None:
# The root block of the graph
self.root_block: List[Node] = []
# Stack of active blocks (lists of nodes) where new nodes are appended
self.block_stack: List[List[Node]] = [self.root_block]
# Inputs to the kernel
self.inputs: List[Node] = []
class GraphBuilder:
def __init__(self) -> None:
# The root block of the graph
self.root_block: List[Node] = []
# Stack of active blocks (lists of nodes) where new nodes are appended
self.block_stack: List[List[Node]] = [self.root_block]
# Inputs to the kernel
self.inputs: List[Node] = []
self.range_counter: int = 0

Comment on lines +38 to +41
def reset(self) -> None:
self.root_block = []
self.block_stack = [self.root_block]
self.inputs = []

Choose a reason for hiding this comment

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

critical

The range_counter should be reset here to ensure thread-safety and correctness for subsequent kernel traces.

Suggested change
def reset(self) -> None:
self.root_block = []
self.block_stack = [self.root_block]
self.inputs = []
def reset(self) -> None:
self.root_block = []
self.block_stack = [self.root_block]
self.inputs = []
self.range_counter = 0

Comment on lines +67 to +68
except Exception as e:
print(f"WARNING: Failed to insert partial schedule: {e} for {mupa_str}")

Choose a reason for hiding this comment

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

high

Catching a broad Exception and only printing a warning can hide critical errors during schedule construction. If creating the MultiUnionPwAff fails, it likely indicates a fundamental problem with the SCoP extraction or the mupa_str formatting. This error should be propagated to aid debugging.

Suggested change
except Exception as e:
print(f"WARNING: Failed to insert partial schedule: {e} for {mupa_str}")
except Exception as e:
raise RuntimeError(f"Failed to create partial schedule from: {mupa_str}") from e

Comment on lines +141 to +148
# Note: AstToGraphConverter does NOT preserve original directives attached to range(),
# because they are lost when converting to ISL AST (unless marked).
# To support directives with Polyhedral model, we need to add marks in Schedule tree.

# For now, if we want directives to appear, we rely on the fact that user manually adds them via schedule API,
# OR we implement a mechanism to carry them over.
# The user request "with (C.range(10) | C.parallel())" implies they want it in the final code.
# Since we reconstruct graph from ISL AST, these directives are currently LOST.

Choose a reason for hiding this comment

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

high

As noted in the comments, directives like parallel() are currently lost during the polyhedral compilation pipeline (graph -> SCoP -> ISL AST -> graph). This means that although the frontend syntax is present, it has no effect on the final generated code. This is a significant functional gap that could be misleading to users.

To fix this, the directives need to be propagated through the polyhedral model. A common way to do this is to associate them with loops during SCoP construction and then use isl_schedule_node_insert_mark to insert mark nodes into the ISL schedule tree. The AstToGraphConverter would then need to recognize these marks and re-create the directive nodes in the final graph.

Comment on lines +18 to +33
__all__ = [
"vars",
"range",
"kernel",
"Tensor",
"TensorSpec",
"float32",
"int32",
"f32",
"i32",
"DType",
"when",
"parallel",
"vectorize",
"unroll",
]

Choose a reason for hiding this comment

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

medium

The __all__ list is not alphabetically sorted. Sorting it improves readability and maintainability, making it easier to see what is exported from the module.

Suggested change
__all__ = [
"vars",
"range",
"kernel",
"Tensor",
"TensorSpec",
"float32",
"int32",
"f32",
"i32",
"DType",
"when",
"parallel",
"vectorize",
"unroll",
]
__all__ = [
"DType",
"Tensor",
"TensorSpec",
"f32",
"float32",
"i32",
"int32",
"kernel",
"parallel",
"range",
"unroll",
"vars",
"vectorize",
"when",
]

self.root_block: List[Node] = []
# Stack of active blocks (lists of nodes) where new nodes are appended
self.block_stack: List[List[Node]] = [self.root_block]
# Inputs to the kernel

Choose a reason for hiding this comment

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

medium

The inputs attribute is a list. In caten/kernel.py, there's a check if arg.node not in builder.inputs which is an O(n) operation. For kernels with many input tensors, this could be a performance bottleneck during tracing. Using a dictionary would provide O(1) lookups while preserving insertion order (in Python 3.7+).

This would require updating register_input to use self.inputs[node] = True, reset to use self.inputs = {}, and the compile method in ClangRuntime to use list(builder.inputs).

Suggested change
# Inputs to the kernel
self.inputs: Dict[Node, bool] = {}

...

# Execute in the complement domain of the previous 'when'
with C.otherwise():

Choose a reason for hiding this comment

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

medium

The design document mentions with C.otherwise(): and C.alloc() (line 176), but these features do not appear to be implemented in this pull request. This could be confusing for users reading the documentation. It would be clearer to either remove these for now or mark them explicitly as "planned" or "future work".

@gemini-code-assist
Copy link

Summary of Changes

Hello @hikettei, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request represents a substantial architectural overhaul of the Caten compiler. It establishes a robust frontend Domain-Specific Language (DSL) for defining tensor computations, backed by a comprehensive Intermediate Representation (IR) built from Node objects. The changes introduce a refined polyhedral compilation pipeline that leverages symbolic execution to trace Python code into an IR graph, converts it into a Static Control Part (SCoP) for optimization using ISL, and then renders it into C code. This foundational work significantly advances Caten's capabilities for advanced compiler optimizations and multi-backend code generation.

Highlights

  • Frontend DSL and Tracing Mechanism: Introduced a new caten.kernel module with a @kernel decorator, Symbol for symbolic variables, Directive for loop transformations (parallel, vectorize, unroll), and range/when context managers for control flow. A GraphBuilder in caten.trace enables symbolic execution to dynamically build the IR graph.
  • Refactored Intermediate Representation (IR): The caten.ops module was completely refactored to define a comprehensive set of OpType enums (UnaryOps, BinaryOps, TernaryOps, MemoryOps, ControlOps, MetaOps) and a Node class, forming the core of the new IR graph representation. This also includes UPat and PatternMatcher for graph optimization.
  • Enhanced Polyhedral Integration: Significant changes in caten.polyhedral with new modules (ast_visitor.py, converter.py, scop.py) and a refactored schedule.py. This pipeline now builds a PolyhedralSchedule from the traced IR graph, converts ISL AST back to Caten's IR graph, and extracts Static Control Part (SCoP) information.
  • New Frontend Tensor Interface: A new Tensor class in caten.tensor acts as the primary user interface, allowing definition of tensor shapes and dtypes via TensorSpec. It overloads __getitem__ and __setitem__ to emit LOAD and STORE IR nodes during tracing.
  • Runtime Abstraction and Clang Backend: Added abstract Runtime and CompiledKernel classes in caten.runtime, along with a concrete ClangRuntime and ClangRenderer in caten.runtimes.clang. This enables code generation and compilation to C from the Caten IR graph.
  • Updated Documentation, Examples, and Tests: The docs/IR_AND_DESIGN.md file has been extensively rewritten to reflect the new architecture. New examples (examples/directives.py, examples/e2e_matmul.py) and tests (test/test_control_flow.py, test/test_pattern_matcher.py) demonstrate the new features and ensure correctness.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a significant and well-structured rewrite of the core IR and compilation pipeline. The introduction of a tracing-based frontend, a multi-level IR, and integration with polyhedral scheduling via ISL is a massive step forward. The code is generally clean and demonstrates a strong architectural vision. My review focuses on several key areas: strengthening the tracing mechanism to handle outputs and keyword arguments, improving robustness in the pattern matcher and exception handling, reducing code duplication, and aligning the documentation with the implementation. There are a few critical and high-severity issues related to the tracing design and documentation that should be addressed, but overall this is an impressive and promising contribution.

Comment on lines +146 to +149
_ = func(*func_args)

# 4. Finalize Graph
full_graph = builder.root_block

Choose a reason for hiding this comment

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

critical

The current tracing mechanism does not identify the output nodes of the kernel. The return value of the traced function is discarded (_ = func(*func_args)), and the entire root_block is passed to the compiler. This prevents dead code elimination (via the unimplemented resolve_graph) and means many unnecessary intermediate nodes are processed.

A mechanism to designate outputs is needed. For example, the kernel function's return statement could be used to identify the output tensor(s). The wrapper would then capture this return value and use it to determine the actual output nodes for the graph.

Comment on lines +132 to +135
def _to_node(obj: Any) -> Node:
if isinstance(obj, Node):
return obj
return Node(MetaOps.CONST, (), arg=obj)

Choose a reason for hiding this comment

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

high

The _to_node helper function is re-implemented here, but it already exists in caten/ops.py. This code duplication can lead to inconsistencies and maintenance issues. This local implementation should be removed, and the function should be imported from caten.ops instead.

Comment on lines +43 to +47
global _range_counter
self.args = args
self.iter_sym = Symbol(f"i{_range_counter}")
self.directives: List[Directive] = []
_range_counter += 1

Choose a reason for hiding this comment

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

high

Using a global counter _range_counter for generating unique symbol names is not thread-safe. If kernel compilation were to be parallelized in the future, this could lead to race conditions and non-unique symbol names. Consider using a thread-local counter or passing a context object through the compilation pipeline to manage state like this.

Comment on lines +129 to +137
if args:
for arg in args:
if isinstance(arg, Tensor):
func_args.append(arg)
if arg.node.op == MetaOps.PLACEHOLDER:
if arg.node not in builder.inputs:
builder.register_input(arg.node)
else:
func_args.append(arg)

Choose a reason for hiding this comment

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

high

The logic for creating placeholder nodes for function arguments only handles positional arguments (args). If tensors are passed as keyword arguments, they will be missed, leading to incorrect tracing. The argument handling should be updated to correctly process both positional and keyword arguments, perhaps by using inspect.signature.bind to map all provided arguments to their corresponding parameters.

Comment on lines 58 to +109
* **Methods**:
* `optimize()`: Apply transformations (tiling, fusion).
* `lower()`: Convert to target-specific code string.

### `caten.polyhedral.ScheduleTree` (Wrappers)
* **`Domain`**: Root of the tree, defines the iteration space.
* **`Band`**: Represents a loop nest. Handles tiling, permuting.
* **`Filter`**: Selects a subset of the domain (or specific statements) for the subtree.
* **`Sequence`**: Specifies sequential execution order of children.
* **`Mark`**: Attaches metadata (e.g., "SIMD", "Unroll").

### `caten.render.Renderer`
* **Responsibility**: Visiting the AST/IR and emitting string code.
* **Subclasses**: `CRenderer`, `CUDARenderer`, `MetalRenderer`.
* **Input**: `isl_ast_node` (from Polyhedral) + `ops` graph.
* **Output**: Source code string.

### `caten.runtime.Runtime`
* **Responsibility**: Hardware abstraction layer.
* `lower(target="c")`: Returns target-specific source code string.
* `compile()`: JIT compiles and returns a callable Python executable.

Choose a reason for hiding this comment

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

high

The documentation for caten.kernel.Kernel lists lower() and compile() as methods. However, the implementation in caten/kernel.py does not have these methods on the Kernel class. The compilation logic is handled within the @C.kernel decorator. The documentation should be updated to accurately reflect the class's API and the role of the decorator.

if isinstance(arg, Tensor):
func_args.append(arg)
if arg.node.op == MetaOps.PLACEHOLDER:
if arg.node not in builder.inputs:

Choose a reason for hiding this comment

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

medium

Checking for an item's existence in a list (builder.inputs) is an O(n) operation. For kernels with many input tensors, this could become a minor performance bottleneck during tracing. Using a set for builder.inputs would make this check an O(1) operation on average.

Comment on lines +67 to +68
except Exception as e:
print(f"WARNING: Failed to insert partial schedule: {e} for {mupa_str}")

Choose a reason for hiding this comment

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

medium

Catching a generic Exception can hide bugs and make debugging difficult. It's better to catch more specific exceptions that you expect isl to raise (e.g., I.Error). Also, printing a warning to stdout is not ideal for a library. Consider using Python's logging module, which allows users of the library to control the verbosity and destination of such messages.

Comment on lines +141 to +175
# Note: AstToGraphConverter does NOT preserve original directives attached to range(),
# because they are lost when converting to ISL AST (unless marked).
# To support directives with Polyhedral model, we need to add marks in Schedule tree.

# For now, if we want directives to appear, we rely on the fact that user manually adds them via schedule API,
# OR we implement a mechanism to carry them over.
# The user request "with (C.range(10) | C.parallel())" implies they want it in the final code.
# Since we reconstruct graph from ISL AST, these directives are currently LOST.

# To fix this:
# We need to associate directives with the statement or loop in SCoP construction,
# and then re-apply them during scheduling or rendering.
# ISL supports 'mark' nodes. We can insert marks for directives.

# HOWEVER, for this turn, I'll just implement the syntax support and rendering capability.
# Connecting them through ISL requires deeper changes (inserting marks in schedule).

# Wait, if I use "Polyhedral Generated Kernel", I'm going through ISL.
# If I want to demonstrate directives, maybe I should skip ISL for a simple example?
# No, the requirement is strict about Polyhedral.

# I will leave the ISL integration part of directives as a limitation/TODO for now,
# as correct propagation requires AST generation callbacks or schedule tree manipulation.

# But to satisfy "PatternMatcher is not implemented", I prioritized that.

# Back to rendering:
# AstToGraphConverter uses the ISL AST.
# If we want directives, we need to modify PolyhedralSchedule to insert marks based on SCoP info.
# ScopStatementInfo needs to store directives? No, Range directives belong to loops, not statements directly.

# This is complex. I will implement the syntax and the renderer support.
# Propagation through ISL is out of scope for "PatternMatcher implementation" task?
# The user asked for "2. with (C.range(10) | C.parallel()) ... examples".

Choose a reason for hiding this comment

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

medium

This block contains extensive comments explaining design limitations and future work (e.g., loss of directives through the ISL round-trip). While insightful, this kind of documentation is better suited for the design document (docs/IR_AND_DESIGN.md) or as TODO comments in the code. Keeping long, explanatory prose inside a method clutters the implementation.

Comment on lines +6 to +12
class ASTNodeType:
ERROR = -1
FOR = 1
IF = 2
BLOCK = 3
MARK = 4
USER = 5

Choose a reason for hiding this comment

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

medium

The ASTNodeType class is defined with class attributes to represent constants. For better type safety and clarity, this should be defined as a proper enumeration using enum.IntEnum.

Suggested change
class ASTNodeType:
ERROR = -1
FOR = 1
IF = 2
BLOCK = 3
MARK = 4
USER = 5
from enum import IntEnum
class ASTNodeType(IntEnum):
ERROR = -1
FOR = 1
IF = 2
BLOCK = 3
MARK = 4
USER = 5

Comment on lines +18 to +33
__all__ = [
"vars",
"range",
"kernel",
"Tensor",
"TensorSpec",
"float32",
"int32",
"f32",
"i32",
"DType",
"when",
"parallel",
"vectorize",
"unroll",
]

Choose a reason for hiding this comment

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

medium

For better maintainability and easier navigation, it's a good practice to keep the __all__ list sorted alphabetically.

Suggested change
__all__ = [
"vars",
"range",
"kernel",
"Tensor",
"TensorSpec",
"float32",
"int32",
"f32",
"i32",
"DType",
"when",
"parallel",
"vectorize",
"unroll",
]
__all__ = [
"DType",
"Tensor",
"TensorSpec",
"f32",
"float32",
"i32",
"int32",
"kernel",
"parallel",
"range",
"unroll",
"vars",
"vectorize",
"when",
]

@hikettei
Copy link
Owner Author

import caten as C
import caten.polyhedral as P

↑だけで全てのAPIが使えるべき、テストやサンプルコードもそれに従うべき

@hikettei
Copy link
Owner Author

グラフは常にDAG リストを作るな

@hikettei
Copy link
Owner Author

get_kernelはデコレーターではなく、wrapped functionへ、、、

@hikettei hikettei closed this Dec 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant