Skip to content
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

Added TensorFlow support to nncf.Tensor #3106

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

olegkkruglov
Copy link

Changes

  • Added tf_numeric.py and tf_linalg.py files with implementations of methods needed for nncf.Tensor support.
  • Added TensorFlow backend for nncf.Tensor.
  • Fixed bug in __ifloordiv__ operator for nncf.Tensor.
  • Added related tests.

Reason for changes

Currently TensorFlow tensors are not supported by nncf.Tensor. It prevents #3041 from being done.

Related tickets

#3041

Tests

TestTFNNCFTensorOperators and TestGPUTFNNCFTensorOperators classes were added to tests/tensorflow/test_tensor.py. Some changes were necessary for tests/cross_fw/test_templates/template_test_nncf_tensor.py, mostly related to different device management in TensorFlow.

@github-actions github-actions bot added the NNCF TF Pull requests that updates NNCF TensorFlow label Nov 22, 2024
@github-actions github-actions bot added the documentation Improvements or additions to documentation label Nov 22, 2024
@olegkkruglov olegkkruglov marked this pull request as ready for review November 22, 2024 17:01
@olegkkruglov olegkkruglov requested a review from a team as a code owner November 22, 2024 17:01
@kshpv kshpv requested a review from alexsu52 November 28, 2024 13:45
@alexsu52
Copy link
Contributor

alexsu52 commented Dec 6, 2024

Please, update your branch from develop.

@kshpv kshpv self-requested a review December 6, 2024 09:43
nncf/tensor/functions/tf_numeric.py Outdated Show resolved Hide resolved

@numeric.squeeze.register(tf.Tensor)
def _(a: tf.Tensor, axis: Optional[Union[int, Tuple[int, ...]]] = None) -> tf.Tensor:
with tf.device(a.device):
Copy link
Collaborator

Choose a reason for hiding this comment

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

I do not see a reason to strictly return the backend for the TF tensor.
@alexsu52, do you think this is necessary? It looks like the device management for TF is kinda auto

Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I know, TF has default device which is used to create any new tensor. Default is GPU if applicable. The function has to return tensor on the same device. I think using with tf.device(a.device): is right.

nncf/tensor/functions/tf_numeric.py Outdated Show resolved Hide resolved
nncf/tensor/functions/tf_numeric.py Outdated Show resolved Hide resolved
axis: Union[int, Tuple[int, ...]] = None,
keepdims: bool = False,
) -> tf.Tensor:
numpy_a = np.array(a)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we add tensorflow_probability package for calculation median here? @alexsu52

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that this is good idea because it adds new dependence in NNCF.

nncf/tensor/functions/tf_numeric.py Outdated Show resolved Hide resolved
nncf/tensor/functions/tf_numeric.py Outdated Show resolved Hide resolved
nncf/tensor/functions/tf_numeric.py Outdated Show resolved Hide resolved
@@ -112,7 +112,8 @@ def test_operators_tensor(self, op_name):
assert res.dtype == res_nncf.data.dtype
assert all(res == res_nncf.data)
assert isinstance(res_nncf, Tensor)
assert res_nncf.device == nncf_tensor_a.device
if not (self.backend() == TensorBackend.tf and self.device() == TensorDeviceType.CPU):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you briefly explain the reason for these changes while you return specific device tensors for TF?

Copy link
Author

Choose a reason for hiding this comment

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

the result of binary operation with two CPU TF tensors is GPU TF tensor by default. it means that the following check would fail on CPU.

@@ -158,7 +164,7 @@ def test_comparison_tensor(self, op_name):
res = fn(tensor_a, tensor_b)
res_nncf = fn(nncf_tensor_a, nncf_tensor_b)

assert res == res_nncf
assert res_nncf == res
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you clarify why you changed the order here?

Copy link
Author

Choose a reason for hiding this comment

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

with the old order comparison operator for tf.Tensor was called here, it tries to convert nncf.Tensor to tf.EagerTensor. It causes a problem because it calls __len__ operator somewhere inside. I tried to implement __len__ operator for nncf.Tensor as return len(self._data) but the comparison still fails for scalar tensors. currently I have no idea how to resolve it and used changing order here as a quick workaround. I'd appreciate any other suggestions.

Copy link
Contributor

@alexsu52 alexsu52 left a comment

Choose a reason for hiding this comment

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

Thanks for contributing. Please address my comments.
PS: Sorry for delay with reviewing.

nncf/tensor/functions/tf_linalg.py Outdated Show resolved Hide resolved
nncf/tensor/functions/tf_linalg.py Outdated Show resolved Hide resolved
nncf/tensor/functions/tf_linalg.py Outdated Show resolved Hide resolved
nncf/tensor/functions/tf_linalg.py Outdated Show resolved Hide resolved
nncf/tensor/functions/tf_linalg.py Outdated Show resolved Hide resolved
axis: Union[int, Tuple[int, ...]] = None,
keepdims: bool = False,
) -> tf.Tensor:
numpy_a = np.array(a)
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that this is good idea because it adds new dependence in NNCF.

nncf/tensor/functions/tf_numeric.py Outdated Show resolved Hide resolved
nncf/tensor/functions/tf_numeric.py Show resolved Hide resolved
nncf/tensor/functions/tf_numeric.py Outdated Show resolved Hide resolved
nncf/tensor/functions/tf_numeric.py Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation NNCF TF Pull requests that updates NNCF TensorFlow
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants