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

Expose arithm ops in Python #1355

Merged
merged 1 commit into from
Oct 21, 2019
Merged

Conversation

klecki
Copy link
Contributor

@klecki klecki commented Oct 8, 2019

Make arithmetic ops accessible from python using python special methods for operator overloading on _EdgeReference.
Supported ops: +, -, *, /, //

Why we need this PR?

So we can use arithmetic Ops in natural way through python API.

What happened in this PR?

  • Explain solution of the problem, new feature added.
    EdgeReference (the return value type of Operator call) was extended with overloaded operators (like add, mul, ...) that place a appropriate ArithmeticGenericOp.
    Additionally artihm_meta is now fully specialized every time.
    A fdiv op was added to reflect python's insistence of producing float in division.
  • What was changed, added, removed?
    EdgeReference from nvidia.dali.edge was deprecated and is replaced by _EdgeReference, that was placed in nvidia.dali.ops.
  • What is most important part that reviewers should focus on?
    Pipeline validation of EdgeReference-like objects, loading of arithmetic ops
  • Was this PR tested? How?
    Jupyter notebook, will add a nose test.
  • Were docs and examples updated, if necessary?
    There is an example utilizing numpy added, in future PRs I will add some image blending but I want to have more backend features available for it.

JIRA TASK: [DALI-1054]

@JanuszL
Copy link
Contributor

JanuszL commented Oct 8, 2019

Any test or example?

@klecki klecki force-pushed the python-arithm-op-2 branch 2 times, most recently from 7acc71c to 130571a Compare October 9, 2019 16:52
@klecki klecki force-pushed the python-arithm-op-2 branch 4 times, most recently from b9d1848 to ced658d Compare October 17, 2019 14:10
@klecki
Copy link
Contributor Author

klecki commented Oct 17, 2019

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [949094]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [949094]: BUILD PASSED

@klecki klecki changed the title [WIP] Arithm ops in Python Arithm ops in Python Oct 17, 2019
# limitations under the License.

def _validate_edge_reference(edge):
# TODO(klecki): adjust to <class 'nvidia.dali.ops._EdgeReference'>
Copy link
Contributor

Choose a reason for hiding this comment

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

it's <class in Python 3, but <type in Python 2, just FYI

def __rmul__(self, other):
return _arithm_op("mul", other, self)

def __truediv__(self, other):
Copy link
Contributor

Choose a reason for hiding this comment

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

What are the semantics here?
Are we promoting division results to floating point?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From now on, yes

def _arithm_op(name, *inputs):
input_desc = ""
for i, input in enumerate(inputs):
input_desc += "&" + str(i)
Copy link
Contributor

Choose a reason for hiding this comment

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

Constants?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is based on master, and constants are in #1391 which is not merger yet. I will add support for constants in a follow-up after this and #1391 are merged.

raise TypeError(("Expected outputs of type compatible with \"EdgeReference\". Received"
" output type \"{}\" does not have the attribute \"{}\" that is required.")
.format(type(edge).__name__, attr))
return True
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: add new line at the end of file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -17,8 +17,17 @@
from nvidia.dali.backend import TensorCPU
from nvidia.dali.backend import TensorListCPU

print("[Warning] nvidia.dali.edge is deprecated. For TensorCPU and TensorListCPU " +
"use nvidia.dali.tensors. EdgeReference is intended to be created only by " +
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"use nvidia.dali.tensors. EdgeReference is intended to be created only by " +
"use nvidia.dali.tensors._EdgeReference is intended to be created only by " +

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No. This is a next sentence.

_load_arithm_ops()

def _choose_device(inputs):
result_device = "cpu"
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion:

result_device = "gpu" if any(in.device == "gpu" for in in inputs) else "cpu

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think a loop is clearer, especially than inlining python weird ternary with it's clunky list-comprehension.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used a version of this actually, but without the ternary.

" left = []\n",
" right = []\n",
" for sample in range(self.batch_size):\n",
" left.append(np.array([sample + self.i], dtype = self.left_type))\n",
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we have this kind of tests also in python tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added one.

@klecki klecki force-pushed the python-arithm-op-2 branch 3 times, most recently from 601f91b to 7c992d7 Compare October 18, 2019 17:18
@klecki
Copy link
Contributor Author

klecki commented Oct 18, 2019

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [951238]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [951238]: BUILD FAILED

@klecki
Copy link
Contributor Author

klecki commented Oct 21, 2019

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [953488]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [953488]: BUILD FAILED

def __rfloordiv__(self, other):
return _arithm_op("div", other, self)

# def __neg__(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

It is some ToDo?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, as we don't have the unary ops implemented yet (they are in next PR).

@klecki
Copy link
Contributor Author

klecki commented Oct 21, 2019

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [953607]: BUILD STARTED

@@ -0,0 +1,170 @@
{
Copy link
Contributor

Choose a reason for hiding this comment

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

You need to add it into docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

"The next step is to define the Pipeline.\n",
"\n",
"We override `Pipeline.iter_setup`, a method called by the pipeline before every `Pipeline.run`, to call the iterator\n",
"and feed the result to `ExternalSource()` operator, referenced by `self.jpeg`, by using `feed_input`."
Copy link
Contributor

Choose a reason for hiding this comment

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

self.jpeg ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

" def define_graph(self): \n",
" self.left = self.left_source()\n",
" self.right = self.right_source()\n",
" return self.left, self.right, self.left + self.right * self.left\n",
Copy link
Contributor

@JanuszL JanuszL Oct 21, 2019

Choose a reason for hiding this comment

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

I would add a comment that now you can operate on tensors in define_graph and DALI under the hood would insert right operators. After all this is all about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -204,75 +176,136 @@ inline DALIDataType TypePromotion(span<DALIDataType> types) {
*/
template <ArithmeticOp op, typename Backend>
struct arithm_meta {
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't it be just forward declared (instead of empty)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -24,8 +24,9 @@
#define ALLOWED_TYPES \
(uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double)

#define ALLOWED_OPS \
(ArithmeticOp::add, ArithmeticOp::sub, ArithmeticOp::mul, ArithmeticOp::div, ArithmeticOp::mod)
#define ALLOWED_OPS \
Copy link
Contributor

Choose a reason for hiding this comment

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

how about defining ALLOWED_TYPES and ALLOWED_OPS only once?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's done in next PR, where I merged the factories.

@@ -24,8 +24,9 @@
#define ALLOWED_TYPES \
(uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double)
Copy link
Contributor

Choose a reason for hiding this comment

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

float16 missing

Copy link
Contributor Author

@klecki klecki Oct 21, 2019

Choose a reason for hiding this comment

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

It's broken. We need to clean up the cpu/gpu types that were merged and don't work. Otherwise the type promotions get complicated.

@klecki
Copy link
Contributor Author

klecki commented Oct 21, 2019

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [953741]: BUILD STARTED

@@ -220,7 +220,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.15+"
"version": "2.7.12"
Copy link
Contributor

Choose a reason for hiding this comment

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

Not needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I <3 jupyter.

@klecki
Copy link
Contributor Author

klecki commented Oct 21, 2019

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [953771]: BUILD STARTED

Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>

Add a test and implement division that results in `float`

Signed-off-by: Krzysztof Lecki <klecki@nvidia.com>
@klecki
Copy link
Contributor Author

klecki commented Oct 21, 2019

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [953834]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [953834]: BUILD PASSED

@klecki klecki changed the title Arithm ops in Python Expose arithm ops in Python Oct 21, 2019
@klecki klecki merged commit 78f78b0 into NVIDIA:master Oct 21, 2019
@klecki klecki deleted the python-arithm-op-2 branch October 21, 2019 17:29
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.

5 participants