Skip to content

Add NVIDIA TransformerEngine - #29403

Merged
carterbox merged 14 commits into
conda-forge:mainfrom
pstjohn:pstjohn/add-transformer-engine
May 1, 2025
Merged

Add NVIDIA TransformerEngine#29403
carterbox merged 14 commits into
conda-forge:mainfrom
pstjohn:pstjohn/add-transformer-engine

Conversation

@pstjohn

@pstjohn pstjohn commented Mar 11, 2025

Copy link
Copy Markdown
Contributor

Checklist

  • Title of this PR is meaningful: e.g. "Adding my_nifty_package", not "updated meta.yaml".
  • License file is packaged (see here for an example).
  • Source is from official source.
  • Package does not vendor other packages. (If a package uses the source of another package, they should be separate packages or the licenses of all packages need to be packaged).
  • If static libraries are linked in, the license of the static library is packaged.
  • Package does not ship static libraries. If static libraries are needed, follow CFEP-18.
  • Build number is 0.
  • A tarball (url) rather than a repo (e.g. git_url) is used in your recipe (see here for more details).
  • GitHub users listed in the maintainer section have posted a comment confirming they are willing to be listed there.
  • When in trouble, please check our knowledge base documentation before pinging a team.

Signed-off-by: Peter St. John <pstjohn@nvidia.com>
@pstjohn pstjohn changed the title initial attempt at transformer engine recipe Add NVIDIA TransformerEngine Mar 11, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Hi! This is the staged-recipes linter and your PR looks excellent! 🚀

@conda-forge-admin

Copy link
Copy Markdown
Contributor

Hi! This is the friendly automated conda-forge-linting service.

I wanted to let you know that I linted all conda-recipes in your PR (recipes/transformer-engine/meta.yaml) and found some lint.

Here's what I've got...

For recipes/transformer-engine/meta.yaml:

  • requirements: host: importlib-metadata>=1.0 must contain a space between the name and the pin, i.e. importlib-metadata >=1.0
  • requirements: run: importlib-metadata>=1.0 must contain a space between the name and the pin, i.e. importlib-metadata >=1.0

For recipes/transformer-engine/meta.yaml:

  • ℹ️ The recipe is not parsable by parser conda-souschef (grayskull). This parser is not currently used by conda-forge, but may be in the future. We are collecting information to see which recipes are compatible with grayskull.
  • ℹ️ The recipe is not parsable by parser conda-recipe-manager. The recipe can only be automatically migrated to the new v1 format if it is parseable by conda-recipe-manager.
  • ℹ️ top-level output has some malformed specs:
  • In section build: `pytorch ==cuda
  • In section host: pytorch =*=cuda*, importlib-metadata>=1.0
  • In section run: `importlib-metadata>=1.0
  • In section run_constrained: pytorch =*=cuda* Requirement spec fields should always be space-separated to avoid known issues in conda-build. For example, instead of name =version=build, use name version.* build`.

This message was generated by GitHub Actions workflow run https://github.com/conda-forge/conda-forge-webservices/actions/runs/13796775976. Examine the logs at this URL for more detail.

Signed-off-by: Peter St. John <pstjohn@nvidia.com>
@conda-forge-admin

conda-forge-admin commented Mar 11, 2025

Copy link
Copy Markdown
Contributor

Hi! This is the friendly automated conda-forge-linting service.

I just wanted to let you know that I linted all conda-recipes in your PR (recipes/transformer-engine/meta.yaml) and found it was in an excellent condition.

I do have some suggestions for making it better though...

For recipes/transformer-engine/meta.yaml:

  • ℹ️ The recipe is not parsable by parser conda-souschef (grayskull). This parser is not currently used by conda-forge, but may be in the future. We are collecting information to see which recipes are compatible with grayskull.
  • ℹ️ transformer-engine-torch output has some malformed specs:
  • In section build: pytorch =*=cuda*
  • In section host: pytorch =*=cuda*
    Requirement spec fields should match the syntax name [version [build]]to avoid known issues in conda-build. For example, instead of name =version=build, use name version.* build. There should be no spaces between version operators and versions either: python >= 3.8 should be python >=3.8.

This message was generated by GitHub Actions workflow run https://github.com/conda-forge/conda-forge-webservices/actions/runs/14780992719. Examine the logs at this URL for more detail.

pstjohn added 5 commits March 11, 2025 14:32
Signed-off-by: Peter St. John <pstjohn@nvidia.com>
Signed-off-by: Peter St. John <pstjohn@nvidia.com>
Signed-off-by: Peter St. John <pstjohn@nvidia.com>
Signed-off-by: Peter St. John <pstjohn@nvidia.com>
Signed-off-by: Peter St. John <pstjohn@nvidia.com>
Comment on lines +18 to +20
- url: https://github.com/NVIDIA/cudnn-frontend/archive/refs/tags/v1.8.0.tar.gz
sha256: 5907bf8baa8f3b74ad430d54027aadd14a0a61166ae4b00c2daece0df384409e
folder: 3rdparty/cudnn-frontend

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is it ok to vendor cudnn-frontend here? I've packaged this at https://github.com/conda-forge/python-cudnn-frontend-feedstock and have been trying to get it to work (unsuccessfully) at #26296 (comment). But this solution looks much simpler 🙂

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah that's a good question. In conversations with the TE team, they work pretty closely with cudnn-frontend and sometimes have odd tags or versions here. I also don't think the repo is set up to be able to pull these dependencies from a source outside 3rdparty. That might be something we could try to fix in subsequent versions though. cudnn-frontend is a header-only library though, so it should be fairly lightweight.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

From https://conda-forge.org/docs/maintainer/guidelines/#generalities

The source should not contain vendored code. If it does:
Package the vendored project separately and specify the needed dependency in the requirements section. Preferred if the vendored code is needed at runtime.
Allow the vendored code, but make sure the license files are included in the about.license field. Usually ok if it's only a build-time dependency (e.g. headers-only library)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Revending headers for compile-time is OK. What's not OK is revending them at runtime. This package is shipping a copy of CUDNN in $PREFIX/targets.

https://dev.azure.com/conda-forge/feedstock-builds/_build/results?buildId=1235681&view=logs&j=df9408f7-e795-500f-143d-aa7735a0ed8b&t=47addc80-ccbf-566b-ee3a-66cdb8436937&l=4381

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah, yes, that is a problem. I moved some headers around so the CMAKE command could find them, but didn't realize they were getting re-distributed. Since we're patching those cmake build flags anyways I'll try to point cmake to the right place to find them in these conda builds

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well it's not easy to get the cmake command to find these in a different location. The alternative could just be to clean these up post-build, right? Let me try doing that.

@pstjohn

pstjohn commented Apr 16, 2025

Copy link
Copy Markdown
Contributor Author

@conda-forge/help-python, ready for review!

@jakirkham

Copy link
Copy Markdown
Member

cc @gforsyth (for review)

@gforsyth gforsyth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi, I have a few questions, largely because I'm not as familiar with this project, so apologies if the questions are off-base.

Overall I think this looks reasonable -- the build links don't appear to be valid, so I haven't been able to review the build logs, which should be looked at before this gets merged in.

Some other questions:

  1. This is for version 1.13, but I see upstream there are releases in the 2.x series -- is the plan to get this version in and then also add those later versions?
  2. In the setup.py upstream, there is support for jax and paddle, in addition to pytorch. I think it's fine to keep things limited to one of those to start with, but it is worth considering if you want to rename the output to reflect that. It might be a little odd if there is (in the future) an explicit transformer_engine_jax, but transformer_engine gets you the pytorch version

Comment thread recipes/transformer-engine/build.sh Outdated
Comment on lines +11 to +12
if [[ ${cuda_compiler_version} == 12.6 ]]; then
export TORCH_CUDA_ARCH_LIST="5.0;6.0;6.1;7.0;7.5;8.0;8.6;8.9;9.0+PTX"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this need to be this restrictive, or can we set 12.6 as the lower bound?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i actually don't think we need this... unless I'm mistaken for some reason, this might have been leftover from the torch build recipe. Anyways, deleted and the build still seems to pass

Comment thread recipes/transformer-engine/meta.yaml Outdated
Comment on lines +60 to +71
{% if cuda_major >= 12 %}
- cuda-driver-dev
- cuda-cudart-dev
- cuda-nvrtc-dev
- cuda-nvtx-dev
- cuda-nvml-dev
- libcublas-dev
- libcusparse-dev
- libcusolver-dev
- cudnn
- cuda-profiler-api
{% endif %}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
{% if cuda_major >= 12 %}
- cuda-driver-dev
- cuda-cudart-dev
- cuda-nvrtc-dev
- cuda-nvtx-dev
- cuda-nvml-dev
- libcublas-dev
- libcusparse-dev
- libcusolver-dev
- cudnn
- cuda-profiler-api
{% endif %}
- cuda-driver-dev
- cuda-cudart-dev
- cuda-nvrtc-dev
- cuda-nvtx-dev
- cuda-nvml-dev
- libcublas-dev
- libcusparse-dev
- libcusolver-dev
- cudnn
- cuda-profiler-api

Since cuda 11 builds are skipped anyway, I think we can remove the conditional here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yup, thanks -- cleaned up some of this logic

Comment thread recipes/transformer-engine/meta.yaml Outdated
Comment on lines +75 to +76
- scipy
- pytorch_scatter

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't see these as requirements upstream -- should they be here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

whoops, probably leftover from another recipe. Removed!

Comment thread recipes/transformer-engine/build.sh Outdated
if [[ ${cuda_compiler_version} != "None" && "$target_platform" == linux-64 ]]; then
export FORCE_CUDA="1"
if [[ ${cuda_compiler_version} == 12.6 ]]; then
export TORCH_CUDA_ARCH_LIST="5.0;6.0;6.1;7.0;7.5;8.0;8.6;8.9;9.0+PTX"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

And is this env-var used by TransformerEngine? Or is this for pytorch?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Probably for pytorch; I actually suspect we could just delete this

Signed-off-by: Peter St. John <pstjohn@nvidia.com>
@pstjohn

pstjohn commented Apr 25, 2025

Copy link
Copy Markdown
Contributor Author

This is for version 1.13, but I see upstream there are releases in the 2.x series -- is the plan to get this version in and then also add those later versions?

Yeah that's right. We may even need to add a 1.12 version; I think I may have overshot the oldest version folks are using. But we'd want to quickly add the 2.x series as well.

In the setup.py upstream, there is support for jax and paddle, in addition to pytorch. I think it's fine to keep things limited to one of those to start with, but it is worth considering if you want to rename the output to reflect that. It might be a little odd if there is (in the future) an explicit transformer_engine_jax, but transformer_engine gets you the pytorch version

IIUC there's not any paddle support anymore? but I'll double check. Anyways yes; that's a good idea. We're going to hopefully clean up the packaging here to make these targets more obvious, but in python currently you use optional dependencies (i.e.transformer_engine[pytorch]) to build the different frontends; which isn't super obvious. It might be easier to move to a transformer_engine_core / transformer_engine_pytorch / transformer_engine_jax type naming structure. Let me check in with the TE team on how they want to handle things here

@gforsyth

Copy link
Copy Markdown
Contributor

It might be easier to move to a transformer_engine_core / transformer_engine_pytorch / transformer_engine_jax type naming structure. Let me check in with the TE team on how they want to handle things here

This change doesn't need to be made upstream -- handling it with optional dependencies is the pattern of choice with pip, but conda doesn't have that option.

I think what you've suggested re: *_core, *_pytorch makes sense to start with. You don't want to have to rugpull any early users by changing what the packages do, but it's an accepted pattern that the names in conda don't match the names on pypi (especially true when things are not Python-specific).

As an example, for the ibis-framework package, we have a LOT of optional backends and the pip->conda translation generally goes as:

ibis-framework['duckdb'] => ibis-duckdb
ibis-framework['postgres'] => ibis-postgres
ibis-framework['snowflake'] => ibis-snowflake

Signed-off-by: Peter St. John <pstjohn@nvidia.com>
@github-actions

Copy link
Copy Markdown
Contributor

Hi! This is the staged-recipes linter and your PR looks excellent but I have some suggestions.

File-specific lints and/or hints:

  • recipes/transformer-engine/meta.yaml:
    • hints:
      • It looks like you are submitting a multi-output recipe. In these cases, the correct name for the feedstock is ambiguous, and our infrastructure defaults to the top-level package.name field. Please add a feedstock-name entry in the extra section.

@pstjohn

pstjohn commented Apr 25, 2025

Copy link
Copy Markdown
Contributor Author

@conda-forge-admin please rerender

@weiji14

weiji14 commented Apr 27, 2025

Copy link
Copy Markdown
Member

It might be easier to move to a transformer_engine_core / transformer_engine_pytorch / transformer_engine_jax type naming structure. Let me check in with the TE team on how they want to handle things here

This change doesn't need to be made upstream -- handling it with optional dependencies is the pattern of choice with pip, but conda doesn't have that option.

FYI, optional dependency groups might be coming to conda soon with this CEP, xref conda/conda#7502 (comment). So you could also just do transformer_engine (core) here first, and handle the jax/pytorch extras later.

pstjohn added 2 commits April 29, 2025 06:45
Signed-off-by: Peter St. John <pstjohn@nvidia.com>
Signed-off-by: Peter St. John <pstjohn@nvidia.com>

@gforsyth gforsyth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice work on this @pstjohn!

@jakirkham jakirkham left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Peter for the contribution! 🙏

Also thanks Gil and Wei for your reviews!

Had a couple suggestions below

"-B",
build_dir,
- f"-DPython_EXECUTABLE={sys.executable}",
+ "-DPython_EXECUTABLE=$PYTHON",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Think we can do this in a more Pythonic way

Suggested change
+ "-DPython_EXECUTABLE=$PYTHON",
+ "-DPython_EXECUTABLE={os.environ['PYTHON']}",

Also what happens when sys.executable is here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sys.executable led to this failure during build:

      CMake Error at /home/conda/staged-recipes/build_artifacts/transformer-engine_1745610886178/_build_env/share/cmake-4.0/Modules/FindPackageHandleStandardArgs.cmake:227 (message):
        Could NOT find Python (missing: Interpreter Development.Module) (found
        version "3.11.12")

@pstjohn pstjohn May 1, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Think we can do this in a more Pythonic way

No oddly, I get the same missing: Interpreter Development.Module when I do f"-DPython_EXECUTABLE={os.environ['PYTHON']}",; at least locally. Not sure why these would be different?

@@ -0,0 +1 @@
export CUDA_HOME=$CONDA_PREFIX

@jakirkham jakirkham Apr 30, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would check if CUDA_HOME is set and if so keep a copy

Suggested change
export CUDA_HOME=$CONDA_PREFIX
if [[ ! -z "${CUDA_HOME +x}" ]]
then
export CUDA_HOME_BACKUP="${CUDA_HOME}"
fi
export CUDA_HOME="${CONDA_PREFIX}"

Then would add a separate deactivate script to restore the original value

if [[ ! -z "${CUDA_HOME_BACKUP+x}" ]]
then
    export CUDA_HOME="${CUDA_HOME_BACKUP}"
    unset CUDA_HOME_BACKUP
fi

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

sure, done

Comment on lines +102 to +104
extra:
recipe-maintainers:
- pstjohn

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
extra:
recipe-maintainers:
- pstjohn
extra:
feedstock-name: transformer-engine
recipe-maintainers:
- pstjohn

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done!

Comment thread recipes/transformer-engine/build_te.sh Outdated
cp $PREFIX/include/cudnn*.h $PREFIX/targets/x86_64-linux/include

echo "Installing transformer-engine"
${PYTHON} -m pip install .

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Logs show that the pip package version metadata contains some kind of hash.

e.g. transformer_engine-1.13.0+6a31486c93

Is this intentional? Or is there an override variable you can set.

https://dev.azure.com/conda-forge/feedstock-builds/_build/results?buildId=1235681&view=logs&j=df9408f7-e795-500f-143d-aa7735a0ed8b&t=47addc80-ccbf-566b-ee3a-66cdb8436937&l=2088

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +69 to +76
- cuda-driver-dev
- cuda-cudart-dev
- cuda-nvrtc-dev
- cuda-nvtx-dev
- cuda-nvml-dev
- libcublas-dev
- libcusparse-dev
- libcusolver-dev

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There are various unused dependencies at runtime from these CUDA libraries. Are we using dlopen or statically linking? Or are the deps actually unused?

https://dev.azure.com/conda-forge/feedstock-builds/_build/results?buildId=1235681&view=logs&j=df9408f7-e795-500f-143d-aa7735a0ed8b&t=47addc80-ccbf-566b-ee3a-66cdb8436937&l=2494

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah good question; they might only be needed at build time. Would I move these from host to build then? I'm pretty sure pydantic just wasn't exercised during the import tests, added an additional import to hopefully hit that.

@carterbox carterbox May 1, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It depends:

statically linked? This should only be cudart. Use the cudart-static package instead.
dlopen'd? Ignore run_exports from these packages and add any relevant constraints to `requirements/run_constrained'
Unused? Remove it.

None of these packages are build tools, so they shouldn't go in requirements/build.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As discussed offline, we are assuming these packages are dlopen'd and will decide whether to make them optional at a later time.

Comment on lines +18 to +20
- url: https://github.com/NVIDIA/cudnn-frontend/archive/refs/tags/v1.8.0.tar.gz
sha256: 5907bf8baa8f3b74ad430d54027aadd14a0a61166ae4b00c2daece0df384409e
folder: 3rdparty/cudnn-frontend

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Revending headers for compile-time is OK. What's not OK is revending them at runtime. This package is shipping a copy of CUDNN in $PREFIX/targets.

https://dev.azure.com/conda-forge/feedstock-builds/_build/results?buildId=1235681&view=logs&j=df9408f7-e795-500f-143d-aa7735a0ed8b&t=47addc80-ccbf-566b-ee3a-66cdb8436937&l=4381

Signed-off-by: Peter St. John <pstjohn@nvidia.com>
@github-actions

github-actions Bot commented May 1, 2025

Copy link
Copy Markdown
Contributor

Hi! This is the staged-recipes linter and your PR looks excellent! 🚀

Comment thread recipes/transformer-engine/activate.sh Outdated
@@ -0,0 +1,5 @@
if [[ ! -z "${CUDA_HOME +x}" ]]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Latest build is failing tests on this line:

2025-05-01T17:46:08.8928287Z /home/conda/staged-recipes/build_artifacts/transformer-engine_1746110968067/_test_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placeho/etc/conda/activate.d/transformer-engine-activate.sh: line 1: ${CUDA_HOME +x}: bad substitution

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Autocomplete kept adding spaces 🤦‍♂️

Thought I removed them all from the suggestion, but this was missed here

Suggested change
if [[ ! -z "${CUDA_HOME +x}" ]]
if [[ ! -z "${CUDA_HOME+x}" ]]

Signed-off-by: Peter St. John <pstjohn@nvidia.com>
@carterbox
carterbox enabled auto-merge May 1, 2025 20:12
@carterbox
carterbox merged commit 8b15ace into conda-forge:main May 1, 2025
@jakirkham

Copy link
Copy Markdown
Member

Thanks all! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants