Skip to content

Recreate python_frontend test_basic for nvfuser_direct #4521

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: direct_pt12
Choose a base branch
from

Conversation

rdspring1
Copy link
Collaborator

@rdspring1 rdspring1 commented May 26, 2025

This PR recreates test_basic, which is the first test from test/python/test_python_frontend.py.

  • It checks correctness against pytorch eager mode and the validity of the python repro via check_captured_python_definition.

New functions to nvfuser_direct FusionDefinition:

  • Added __repr__, define_scalar, and from_pytorch

Updated python/python_next/ir.cpp for define_scalar:

  1. Created define_scalar binding
  2. Added is_symbolic to Val binding

Created pytorch_utils.py for from_pytorch:

  • Added torch_dtype_to_nvfuser_dtype

PR Stack:
#4513 Add bindings for FusionExecutorCache
#4516 Add the remaining binary operations
#4517 Add the bindings for unary operations
#4518 Add the bindings for reduction operations
#4519 Move helper functions from python_frontend to python_common
#4520 Create python reproducer from Fusion IR for nvfuser_direct
#4521 Recreate python_frontend test_basic for nvfuser_direct <<< This PR.

@rdspring1 rdspring1 added Python API Issues related to the Python API Direct Bindings Python extension with direct mapping to NvFuser CPP objects. labels May 26, 2025
Copy link

github-actions bot commented May 26, 2025

Review updated until commit c1b0ee3

Description

  • Added __repr__, define_scalar, and from_pytorch to FusionDefinition

  • Created define_scalar binding in ir.cpp

  • Added is_symbolic to Val binding in ir.cpp

  • Created pytorch_utils.py for torch_dtype_to_nvfuser_dtype


Changes walkthrough 📝

Relevant files
Bindings
ir.cpp
Add define_scalar and is_symbolic bindings                             

python/python_direct/ir.cpp

  • Added define_scalar binding
  • Added is_symbolic to Val binding
  • +39/-2   
    Enhancement
    __init__.py
    Enhance FusionDefinition with new methods                               

    python/nvfuser_direct/init.py

  • Added __repr__ method
  • Added define_scalar method
  • Added from_pytorch method
  • +67/-0   
    Utility
    pytorch_utils.py
    Add torch_dtype_to_nvfuser_dtype function                               

    python/nvfuser_direct/pytorch_utils.py

    • Added torch_dtype_to_nvfuser_dtype function
    +36/-0   
    utils.py
    Add utility functions and NVFuserTest class                           

    tests/python_direct/utils.py

  • Added is_pre_volta, is_pre_ampere, is_pre_hopper functions
  • Added check_captured_python_definition function
  • Added NVFuserTest class
  • +91/-0   
    Tests
    test_python_frontend.py
    Add test_basic for nvfuser_direct                                               

    tests/python_direct/test_python_frontend.py

    • Added test_basic test case
    +42/-0   

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    🧪 PR contains tests
    ⚡ Recommended focus areas for review

    Overloading

    The define_scalar function is overloaded with two definitions. Ensure that this overloading does not cause ambiguity or unexpected behavior.

    void bindScalar(py::module& nvfuser) {
      nvfuser.def(
          "define_scalar",
          [](PolymorphicValue::VariantType value,
             std::optional<PrimDataType> dtype) {
            PolymorphicValue cast_value(
                dtype.has_value() ? castToDtype(std::move(value), dtype.value())
                                  : std::move(value));
            PrimDataType value_dtype(
                dtype.has_value()
                    ? dtype.value()
                    : std::get<PrimDataType>(getDataType(value).type));
            return IrBuilder::create<Val>(value, value_dtype);
          },
          py::arg("value"),
          py::arg("dtype") = std::nullopt,
          py::return_value_policy::reference);
      nvfuser.def(
          "define_scalar",
          [](PrimDataType dtype) {
            return IrBuilder::create<Val>(std::monostate{}, dtype);
          },
          py::arg("dtype") = DataType::Double,
          py::return_value_policy::reference);
    }
    Type Handling

    The torch_dtype_to_nvfuser_dtype function maps Python scalars directly to DataType. Verify that this mapping is correct and does not lead to unintended type conversions.

    complex: DataType.ComplexDouble,
    float: DataType.Double,
    int: DataType.Int,
    bool: DataType.Bool,
    Test Coverage

    The test_basic function checks correctness against PyTorch eager mode. Ensure that additional tests cover more complex scenarios and edge cases.

    @pytest.mark.skipif(is_pre_volta(), reason="Only supported on Volta and newer devices.")
    class TestNvFuserFrontend(NVFuserTest):
        def test_basic(self):
            inputs = [
                torch.ones(2, 4, 8, device="cuda"),
                torch.ones(2, 4, 8, device="cuda"),
            ]
    
            def fusion_func(fd: FusionDefinition):
                t0 = fd.from_pytorch(inputs[0])
                t1 = fd.from_pytorch(inputs[1])
                c0 = fd.define_scalar(3.0)
    
                t2 = fd.ops.add(t0, t1)
                t3 = fd.ops.mul(t2, c0)
                t4 = fd.ops.sum(t3, [-1], False, DataType.Float)
    
                fd.add_output(t4)
    
            # Expected Output is a tensor of 48's
            nvf_out, _ = self.exec_nvfuser(fusion_func, inputs)
            eager_out = torch.sum((inputs[0] + inputs[1]) * 3.0, dim=-1)

    * `test_basic` is the first test from test_python_frontend.
    * Created check_captured_python_definition to check python repro.
    
    * Added `__repr__`, `define_scalar`, and `from_pytorch` to nvfuser_direct `FusionDefinition`
    
    Updated `python/python_next/ir.cpp` for `define_scalar`:
    1. Created `define_scalar` binding
    2. Added `is_symbolic` to `Val` binding
    
    Created `pytorch_utils.py` for `from_pytorch`:
    1. Added `torch_dtype_to_nvfuser_dtype`
    @rdspring1 rdspring1 changed the title Recreate python_fronend test_basic for nvfuser_direct Recreate python_frontend test_basic for nvfuser_direct May 28, 2025
    rdspring1 added a commit that referenced this pull request May 28, 2025
    This PR creates the bindings for `FusionExecutorCache`, allowing fusions
    to run CUDA kernels in `nvfuser_direct`.
    
    Functions bound for `FusionExecutorCache`:
    * get_cuda_kernel
    * get_most_recent_scheduled_ir
    * get_scheduled_ir
    * is_compiled
    * execute
    
    Create `python/python_direct/direct_utils.h` for `python_direct`-only
    helper functions
    * Add `from_pyiterable` and `to_tensor_vector` to and from `at::Tensor`
    and `KernelArgumentHolder`
    
    New function for python `FusionDefinition`:
    * `execute` - It creates FusionExecutorCache if it exists and runs the
    fusion with given input arguments.
    
    Testing
    * Created `test_fusion_execution_cache` and `test_define_tensor`
    
    PR Stack:
    #4409 Create python FusionDefinition for nvfuser_next
    #4513 Add bindings for FusionExecutorCache **<<< This PR.**
    #4516 Add the remaining binary operations
    #4517 Add the bindings for unary operations
    #4518 Add the bindings for reduction operations
    #4519 Move helper functions from python_frontend to python_common
    #4520 Create python reproducer from Fusion IR for nvfuser_direct
    #4521 Recreate python_frontend test_basic for nvfuser_direct
    rdspring1 added a commit that referenced this pull request May 31, 2025
    This PR add the remaining binary operations in preparation for creating
    python reproducers from Fusion IR.
    
    PR Stack:
    #4513 Add bindings for FusionExecutorCache
    #4516 Add the remaining binary operations **<<< This PR.**
    #4517 Add the bindings for unary operations
    #4518 Add the bindings for reduction operations
    #4519 Move helper functions from python_frontend to python_common
    #4520 Create python reproducer from Fusion IR for nvfuser_direct
    #4521 Recreate python_frontend test_basic for nvfuser_direct
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    Direct Bindings Python extension with direct mapping to NvFuser CPP objects. Python API Issues related to the Python API
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    1 participant