-
Notifications
You must be signed in to change notification settings - Fork 621
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
Conversation
Any test or example? |
7acc71c
to
130571a
Compare
b9d1848
to
ced658d
Compare
!build |
CI MESSAGE: [949094]: BUILD STARTED |
CI MESSAGE: [949094]: BUILD PASSED |
# limitations under the License. | ||
|
||
def _validate_edge_reference(edge): | ||
# TODO(klecki): adjust to <class 'nvidia.dali.ops._EdgeReference'> |
There was a problem hiding this comment.
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): |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Constants?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"use nvidia.dali.tensors. EdgeReference is intended to be created only by " + | |
"use nvidia.dali.tensors._EdgeReference is intended to be created only by " + |
There was a problem hiding this comment.
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.
dali/python/nvidia/dali/ops.py
Outdated
_load_arithm_ops() | ||
|
||
def _choose_device(inputs): | ||
result_device = "cpu" |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added one.
601f91b
to
7c992d7
Compare
!build |
CI MESSAGE: [951238]: BUILD STARTED |
CI MESSAGE: [951238]: BUILD FAILED |
7c992d7
to
9695d1b
Compare
!build |
CI MESSAGE: [953488]: BUILD STARTED |
CI MESSAGE: [953488]: BUILD FAILED |
def __rfloordiv__(self, other): | ||
return _arithm_op("div", other, self) | ||
|
||
# def __neg__(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is some ToDo
?
There was a problem hiding this comment.
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).
9695d1b
to
3b8ae7a
Compare
!build |
CI MESSAGE: [953607]: BUILD STARTED |
@@ -0,0 +1,170 @@ | |||
{ |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
docs/examples/expressions.ipynb
Outdated
"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`." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.jpeg
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
docs/examples/expressions.ipynb
Outdated
" 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", |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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)?
There was a problem hiding this comment.
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 \ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
float16
missing
There was a problem hiding this comment.
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.
3b8ae7a
to
433c363
Compare
!build |
CI MESSAGE: [953741]: BUILD STARTED |
docs/examples/external_input.ipynb
Outdated
@@ -220,7 +220,7 @@ | |||
"name": "python", | |||
"nbconvert_exporter": "python", | |||
"pygments_lexer": "ipython2", | |||
"version": "2.7.15+" | |||
"version": "2.7.12" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I <3 jupyter.
433c363
to
f26d280
Compare
!build |
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>
f26d280
to
2f85c47
Compare
!build |
CI MESSAGE: [953834]: BUILD STARTED |
CI MESSAGE: [953834]: BUILD PASSED |
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?
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.EdgeReference
fromnvidia.dali.edge
was deprecated and is replaced by_EdgeReference
, that was placed innvidia.dali.ops
.Pipeline validation of EdgeReference-like objects, loading of arithmetic ops
Jupyter notebook, will add a nose test.
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]