Skip to content

Treat real transposes like adjoint in internal dispatch #1296

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

Merged
merged 3 commits into from
Apr 22, 2025

Conversation

jishnub
Copy link
Member

@jishnub jishnub commented Apr 21, 2025

Since real transposes are equivalent to adjoints, we may compile methods only for one of the two types when we are unwrapping a Transpose through the wrapperop mechanism. This will improve the time to the second execution in certain cases (as the same type will be re-used). This is primarily useful in internal method dispatches where the result of wrapperop will not be returned.

For example, on master

julia> using LinearAlgebra

julia> U = UpperTriangular([1 2; 3 4]);

julia> @time transpose(U) * parent(U);
  0.140280 seconds (552.81 k allocations: 27.080 MiB, 99.90% compilation time)

julia> @time adjoint(U) * parent(U);
  0.124338 seconds (404.18 k allocations: 19.600 MiB, 99.92% compilation time)

whereas, on this PR,

julia> @time transpose(U) * parent(U);
  0.161032 seconds (553.25 k allocations: 27.090 MiB, 8.75% gc time, 99.91% compilation time)

julia> @time adjoint(U) * parent(U);
  0.053536 seconds (356.69 k allocations: 17.240 MiB, 99.81% compilation time)

The second execution is noticeably faster.

@jishnub jishnub added the ttfx The change pertains to first-call latency label Apr 21, 2025
@dkarrasch
Copy link
Member

Nice. Just a quick check: why can't we make this the "official" behaviour for wrapperop? Is it user-facing and would potentially "confuse" users?

@jishnub
Copy link
Member Author

jishnub commented Apr 21, 2025

The current behavior of preserving the type in wrapperop is used in certain functions, e.g. similar and getindex. It seems like a useful behavior to preserve, and we may add another function (or method) that is primarily for optimizations. In the indexing context, it is indeed easier to remember that indexing into an Adjoint block matrix always produces an Adjoint matrix, and not a Transpose in certain cases. Moreover, this change would be strictly non-breaking if the returned types are not altered.

However, this may be a method of wrapperop instead of its own function, as they essentially do the same thing.

Copy link

codecov bot commented Apr 21, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.12%. Comparing base (07725da) to head (ac4fca8).
Report is 3 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1296   +/-   ##
=======================================
  Coverage   92.12%   92.12%           
=======================================
  Files          34       34           
  Lines       15509    15511    +2     
=======================================
+ Hits        14287    14289    +2     
  Misses       1222     1222           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jishnub jishnub merged commit 78e6156 into master Apr 22, 2025
4 checks passed
@jishnub jishnub deleted the jishnub/wrapperop branch April 22, 2025 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ttfx The change pertains to first-call latency
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants