Skip to content

Comparing python objects such as list and tuple with mlx.core.array (#866) - #886

Closed
amirhossein-razlighi wants to merge 0 commit into
ml-explore:mainfrom
amirhossein-razlighi:main
Closed

Comparing python objects such as list and tuple with mlx.core.array (#866)#886
amirhossein-razlighi wants to merge 0 commit into
ml-explore:mainfrom
amirhossein-razlighi:main

Conversation

@amirhossein-razlighi

Copy link
Copy Markdown
Contributor

Proposed changes

This pull request is related to issue #866 . When trying to compare python list or tuple with an mlx.core.array, mlx throws exception. Right now, regarding the comments in the related issue, mlx returns False (following the way it is done in PyTorch). An example is as follows:

import mlx.core as mx

a = mx.array([1, 2, 3])
a == [1, 2, 3] # False
a == mx.array([1,2,3]) # True
a != [1, 2, 3] # True
a == (1, 2) # False

Checklist

Put an x in the boxes that apply.

  • I have read the CONTRIBUTING document
  • I have run pre-commit run --all-files to format my code / installed pre-commit prior to committing changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the necessary documentation (if needed)

Comment thread python/src/array.cpp Outdated
Comment thread python/src/array.cpp Outdated

@awni awni 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 for getting this started. Left some comments inline, please address.

Comment thread python/src/utils.h Outdated
Comment thread python/src/array.cpp Outdated
Comment thread python/src/array.cpp Outdated
Comment thread python/src/utils.h Outdated
Comment thread python/src/utils.h Outdated
Comment thread python/src/array.cpp Outdated
Comment thread python/src/array.cpp Outdated
Comment thread python/src/utils.h Outdated
Comment on lines +50 to +60
if (auto pv = std::get_if<nb::bool_>(&v); pv) {
return true;
} else if (auto pv = std::get_if<nb::int_>(&v); pv) {
return true;
} else if (auto pv = std::get_if<nb::float_>(&v); pv) {
return true;
} else if (auto pv = std::get_if<std::complex<float>>(&v); pv) {
return true;
} else if (auto pv = std::get_if<nb::object>(&v); pv) {
return nb::hasattr(*pv, "__mlx_array__") || nb::isinstance<array>(*pv);
}

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.

You had a different version earlier which just pulled out an object if it existed. So if it's not an nb::oject then it's ok (int, bool, float, complex) and if it is then check if its an array or has the attribute? Maybe we should do that instead?

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.

It's the same line that is present here:

else if (auto pv = std::get_if<nb::object>(&v); pv) {
    return nb::hasattr(*pv, "__mlx_array__") || nb::isinstance<array>(*pv);
  }

The function that we had earlier (isMlxCoreArray) checked this line. I think right now it's better and we may use this utility function further in more operations (where we need to check if the operands are valid and can be converted to mlx.core.array).

@awni awni Mar 27, 2024

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.

Ok just thinking about it from an efficiency standpoint (if we wanted to use this in a lot of ops we'd need it to be very fast since it's pure overhead). Can you not do?

if (auto pv = std::get_if<nb::object>(&v); pv) {
    return nb::isinstance<array>(*pv) || nb::hasattr(*pv, "__mlx_array__");
} else {
    return true;
}

Also it might be minor but I would swap the hasattr and the isinstance since the former will be much much more common (and also probably a lot less expensive).

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 swapped the hasattr and isinstance. Also, why should we add else { return true; }? Because if it's not each of the options mentioned above (bool/int/float/complex/array) it is not convertible to array and thus, we should simply return False.

@amirhossein-razlighi amirhossein-razlighi Mar 27, 2024

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.

please check the latest commit and let me know about what you think should be changed

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.

Also, I think we need a better name for this function. Because, instances like list and tuple are actually convertible to mlx.core.array. They are not comparable to arrays. Don't you agree? This name might be a little misleading in further developments

@awni

awni commented Mar 27, 2024

Copy link
Copy Markdown
Member

Looks really nice, thank you! I left a couple comments. Could you please take a look and then we can run tests and merge?

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.

2 participants