Skip to content

Fix grad copies - #1854

Merged
awni merged 3 commits into
mainfrom
fix_grad_copies
Feb 11, 2025
Merged

awni merged 3 commits into
mainfrom
fix_grad_copies

Conversation

@awni

@awni awni commented Feb 10, 2025

Copy link
Copy Markdown
Member

Closes #1853

@angeloskath angeloskath 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.

Weird that this went like this for so long 🤔.

Comment thread python/src/transforms.cpp
py_value_out = fun(*tree[0], **tree[1]);

tree_replace(tree, arrays, a);
tree_fill(tree, arrays);

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.

I would expect that not doing this would result in the *args and **kwargs containing a which can be placeholders. But it doesn't happen, do we need the tree_fill here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

But it doesn't happen

You tested it and it's not the case? That is strange and surprising if so..

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.

I think I did. I ran the test on this PR on mlx before this PR. The list arrays still contains the original inputs. Nothing gets broken 🤷‍♂️

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.

tree_replace(tree, arrays, a) shouldn't do anything as it replaces with the placeholders again.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So the tests definitely pass without it.. but nevertheless I think we should keep it. Here's an example of some odd behavior if we remove it:

import mlx.core as mx

def fun(arrs):
    return arrs[0]

arrs = [mx.array(1.0)]
init_id = id(arrs[0])
mx.grad(fun)(arrs)
final_id = id(arrs[0])
print(init_id, final_id) # ids won't match

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

In fact, maybe I should add that as a test :)

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.

I think it makes sense that it doesn't break. We don't actually use placeholders a la vmap. We just set them to tracers. They keep their primitives and everything. I don't know why I expected them to break. When not tracing you can evaluate tracers fine.

Totally agree that the tree_fill should be there.

@awni
awni merged commit 0a52156 into main Feb 11, 2025
@awni
awni deleted the fix_grad_copies branch February 11, 2025 23:26
faisalmemon pushed a commit to faisalmemon/mlx that referenced this pull request Oct 30, 2025
* fix grad with copies

* add test

* add test
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.

[BUG] Models using nn.Sequential may fail to train following PR #1764

2 participants