Skip to content
Open
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
9 changes: 9 additions & 0 deletions .ci/scripts/test_backend.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ if [[ "$FLOW" == *vulkan* ]]; then
EXTRA_BUILD_ARGS+=" -DEXECUTORCH_BUILD_VULKAN=ON"
fi

if [[ "$FLOW" == *cuda* ]]; then
# Fix libstdc++ GLIBCXX version for CUDA backend.
# The embedded .so files in the CUDA blob require GLIBCXX_3.4.30
# which the default conda libstdc++ doesn't have.
echo "Installing newer libstdc++ for CUDA backend..."
conda install -y -c conda-forge 'libstdcxx-ng>=12'
export LD_LIBRARY_PATH="${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH:-}"
fi

if [[ "$FLOW" == *arm* ]]; then

# Setup ARM deps.
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/test-backend-cuda.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Test CUDA Backend

on:
schedule:
- cron: 0 2 * * *
push:
branches:
- release/*
tags:
- ciflow/nightly/*
pull_request:
paths:
- .github/workflows/test-backend-cuda.yml
- .github/workflows/_test_backend.yml
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}--${{ github.event.pull_request.number || github.sha }}-${{ github.event_name == 'workflow_dispatch' }}
cancel-in-progress: true

jobs:
test-cuda:
uses: ./.github/workflows/_test_backend.yml
with:
backend: cuda
flows: '["cuda"]'
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
timeout: 120
run-linux: true
runner-linux: linux.g5.4xlarge.nvidia.gpu
71 changes: 71 additions & 0 deletions backends/cuda/test/tester.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

from typing import Any, List, Optional, Tuple

import executorch
import executorch.backends.test.harness.stages as BaseStages
import torch
from executorch.backends.cuda.cuda_backend import CudaBackend
from executorch.backends.cuda.cuda_partitioner import CudaPartitioner
from executorch.backends.test.harness import Tester as TesterBase
from executorch.backends.test.harness.stages import StageType
from executorch.exir import EdgeCompileConfig
from executorch.exir.backend.partitioner import Partitioner


def _create_default_partitioner() -> CudaPartitioner:
"""Create a CudaPartitioner with default compile specs."""
compile_specs = [CudaBackend.generate_method_name_compile_spec("forward")]
return CudaPartitioner(compile_specs)


class ToEdgeTransformAndLower(BaseStages.ToEdgeTransformAndLower):
"""CUDA-specific ToEdgeTransformAndLower stage."""

def __init__(
self,
partitioners: Optional[List[Partitioner]] = None,
edge_compile_config: Optional[EdgeCompileConfig] = None,
):
if partitioners is None:
partitioners = [_create_default_partitioner()]

super().__init__(
default_partitioner_cls=_create_default_partitioner,
partitioners=partitioners,
edge_compile_config=edge_compile_config
or EdgeCompileConfig(_check_ir_validity=False),
)


class CudaTester(TesterBase):
"""
Tester subclass for CUDA backend.

This tester defines the recipe for lowering models to the CUDA backend
using AOTInductor compilation.
"""

def __init__(
self,
module: torch.nn.Module,
example_inputs: Tuple[torch.Tensor],
dynamic_shapes: Optional[Tuple[Any]] = None,
):
stage_classes = (
executorch.backends.test.harness.Tester.default_stage_classes()
| {
StageType.TO_EDGE_TRANSFORM_AND_LOWER: ToEdgeTransformAndLower,
}
)

super().__init__(
module=module,
stage_classes=stage_classes,
example_inputs=example_inputs,
dynamic_shapes=dynamic_shapes,
)
9 changes: 9 additions & 0 deletions backends/test/suite/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,13 @@ def all_flows() -> dict[str, TestFlow]:
except Exception as e:
logger.info(f"Skipping ARM flow registration: {e}")

try:
from executorch.backends.test.suite.flows.cuda import CUDA_TEST_FLOW

flows += [
CUDA_TEST_FLOW,
]
except Exception as e:
logger.info(f"Skipping CUDA flow registration: {e}")

return {f.name: f for f in flows if f is not None}
21 changes: 21 additions & 0 deletions backends/test/suite/flows/cuda.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

from executorch.backends.cuda.test.tester import CudaTester
from executorch.backends.test.suite.flow import TestFlow


def _create_cuda_flow(name: str = "cuda") -> TestFlow:
"""Create a test flow for the CUDA backend."""
return TestFlow(
name,
backend="cuda",
tester_factory=CudaTester,
quantize=False,
)


CUDA_TEST_FLOW = _create_cuda_flow("cuda")
Loading