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

Per frame brightness contrast #3937

Merged
merged 14 commits into from
Jun 14, 2022

Conversation

stiepan
Copy link
Member

@stiepan stiepan commented May 26, 2022

Category:

New feature (non-breaking change which adds functionality)

Description:

  • Adds per-frame parameters support to color-manipulating operators.
  • Makes contrast_center parameter per-sample (and per-frame too) for the sake of completeness.
  • Adds unfloded_views_range utility to simplify handling of frame-like inputs in an operator when SequenceOperator may be overkill or cannot be used (either because unfolding of arbitrary layout is needed or broadcasting all arguments to match an unfolded sequence-like input may be unnecessary).

Additional information:

Affected modules and functionalities:

  • color_twist (hue, hsv, saturation, color_twist)
  • brightness_contrast (brightness_contrast, brightness, contrast)

Key points relevant for the review:

Checklist

Tests

  • Existing tests apply
  • New tests added
    • Python tests
    • GTests
    • Benchmark
    • Other
  • N/A

Documentation

  • Existing documentation applies
  • Documentation updated
    • Docstring
    • Doxygen
    • RST
    • Jupyter
    • Other
  • N/A

DALI team only

Requirements

  • Implements new requirements
  • Affects existing requirements
  • N/A

REQ IDs: CTSTOPS.05, BRICON.06

JIRA TASK: DALI-2804

@stiepan
Copy link
Member Author

stiepan commented May 26, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4943793]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4943793]: BUILD FAILED

@stiepan
Copy link
Member Author

stiepan commented May 26, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4944005]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4944005]: BUILD PASSED

@stiepan stiepan marked this pull request as ready for review May 27, 2022 09:12
public:
CombinedRange(Range &&range, Ranges &&...ranges)
: ranges_{std::make_tuple(std::forward<Range>(range), std::forward<Ranges>(ranges)...)} {
assert(((range.NumSlices() == ranges.NumSlices()) && ...));
Copy link
Contributor

@mzient mzient May 27, 2022

Choose a reason for hiding this comment

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

Fold expressions are a C++17 feature - this will break debug builds with NVCC 10.2.

Suggested change
assert(((range.NumSlices() == ranges.NumSlices()) && ...));
#if __cplusplus >= 201703L
assert(((range.NumSlices() == ranges.NumSlices()) && ...));
#endif

Copy link
Member Author

Choose a reason for hiding this comment

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

done, I disabled the whole CombinedRange, as the std::apply is also part of c++17

Comment on lines 115 to 116
auto in_view = view<const InputType, ndim>(input[sample_id]);
auto out_view = view<OutputType, ndim>(output[sample_id]);
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 cheaper to get the view to the whole batch and then index:

auto in_view_batch = view<const InputType, ndim>(input);
auto out_view_batch = view<OutputType, ndim>(output);
for (int sample_id = 0; sample_id < num_samples; sample_id++) {
    auto in_view = in_view_batch[sample_id];
    auto out_view = out_view_batch[sample_id];
    

Copy link
Member Author

Choose a reason for hiding this comment

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

done

Comment on lines 150 to 151
auto in_view = view<const InputType, ndim>(input[i]);
auto out_view = view<OutputType, ndim>(output[i]);
Copy link
Contributor

Choose a reason for hiding this comment

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

here as well. View first, index later is cheaper

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, done!

Comment on lines 146 to 147
for (has_3_dims, use_const_contr_center) in rng.sample([
(b1, b2) for b1 in [True, False] for b2 in [True, False]], 2):
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this is to limit the number of combinations? Just asking, do we have any risks of missing some important combination?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it is just for this reason. I don't think so, that's why I left it to (pseudo) chance. :)

using ValueType = std::tuple<typename Range::ValueType, typename Ranges::ValueType...>;

ValueType operator[](IndexType idx) const {
return std::apply([&idx](const auto &...ranges) { return std::make_tuple(ranges[idx]...); },
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick:

Suggested change
return std::apply([&idx](const auto &...ranges) { return std::make_tuple(ranges[idx]...); },
return std::apply([idx](const auto &...ranges) { return std::make_tuple(ranges[idx]...); },

would do I think

Copy link
Member Author

Choose a reason for hiding this comment

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

done

namespace dali {
namespace sequence_utils {

template <typename Storage, typename T, int ndim, int ndims_to_unfold>
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add some docstrings? Looking at this file alone is not enough to understand its purpose. I think

Copy link
Member Author

Choose a reason for hiding this comment

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

done

}

template <typename Range, typename... Ranges>
class CombinedRange {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you also add some docstrings here?

Copy link
Member Author

Choose a reason for hiding this comment

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

done

@stiepan
Copy link
Member Author

stiepan commented May 29, 2022

!build

Comment on lines -114 to -143
template <typename Range>
class RangeIterator {
using IndexType = typename Range::IndexType;
using ValueType = typename Range::ValueType;

public:
RangeIterator(const Range &range, IndexType idx) : range_{range}, idx_{idx} {}

ValueType operator*() const {
return range_[idx_];
}

bool operator==(const RangeIterator &other) const {
return idx_ == other.idx_;
}

bool operator!=(const RangeIterator &other) const {
return !(*this == other);
}

void operator++() {
++idx_;
}

private:
const Range &range_;
IndexType idx_;
};

Copy link
Member Author

Choose a reason for hiding this comment

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

Moved to sequence_utils.h

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4962954]: BUILD FAILED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4963005]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4963005]: BUILD FAILED

@stiepan
Copy link
Member Author

stiepan commented May 30, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4965549]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4965549]: BUILD FAILED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4965549]: BUILD PASSED

Copy link
Contributor

@klecki klecki left a comment

Choose a reason for hiding this comment

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

Some comments

}

bool operator==(const RangeIterator &other) const {
return idx_ == other.idx_;
Copy link
Contributor

Choose a reason for hiding this comment

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

I know this is a copy, but can two iterators that "point to" different ranges be equal if the point at the same index?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can keep it as is for efficiency and assert that the collection is the same - it's a coding error and we can say it's UB to compare iterators from different collections.

assert(view_.shape.size() >= ndims_to_unfold);
return volume(view_.shape.first(ndims_to_unfold));
}()},
slice_shape_{view_.shape.last(out_ndim)},
Copy link
Contributor

Choose a reason for hiding this comment

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

Does last work with DynamicDimensions?

Copy link
Member Author

Choose a reason for hiding this comment

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

fix'd

template <int ndims_to_unfold, typename... Storages, typename... Ts, int... ndims>
CombinedRange<UnfoldedViewRange<Storages, Ts, ndims, ndims_to_unfold>...> unfolded_views_range(
const TensorView<Storages, Ts, ndims> &...views) {
return combine_ranges(unfolded_view_range<ndims_to_unfold>(views)...);
Copy link
Contributor

Choose a reason for hiding this comment

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

Any error checking for the equal volume of unfolded dimensions or we just #yolo?

Copy link
Member Author

Choose a reason for hiding this comment

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

There an assert in combine ranges for equal length of the zipped ranges. I could simply change it to DALI_ENFORCE, but as I am using it in the context of video processing operators, where the number of frames is set by the operator to match the one from the input, it seems superfluous. We don't really check that if doing it manually. I stated in the docs the volumes must be equal, there is an assert, my opinion would be to check it manually before calling the utility if that is not something that follows from the usage logic. But maybe we prefer being on safe side and one extra == check per each sample in batch is fair price to pay, I won't argue if you insist.

@@ -31,12 +32,12 @@ This operator can also change the type of data.)code")
.NumOutput(1)
.AddOptionalArg("brightness",
"Brightness mutliplier.",
kDefaultBrightness, true)
kDefaultBrightness, true, true)
Copy link
Contributor

Choose a reason for hiding this comment

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

General remark, how about adding a dedicated enum for the PerFrame option rather than having the growing true, true chain. Ofc in another PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I was thinking about flags.


using Kernel = kernels::MultiplyAddCpu<OutputType, InputType, 3>;
kernel_manager_.Initialize<Kernel>();
kernel_manager_.template Resize<Kernel>(1);
Copy link
Contributor

Choose a reason for hiding this comment

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

In the original implementation it was max_batch_size_ here.

Copy link
Member Author

Choose a reason for hiding this comment

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

It was, but then the operator called all the samples with the kernel instance of idx 0.

@@ -626,3 +626,16 @@ def gen():
def as_array(tensor):
import_numpy()
return np.array(tensor.as_cpu() if isinstance(tensor, TensorGPU) else tensor)


def python_function(*inputs, function, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this supposed to be doing? Can you add a docstring? The name is pretty generic.

Copy link
Member Author

Choose a reason for hiding this comment

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

done

video_test_cases = [
(fn.hue, {}, [ArgCb("hue", hue, True)]),
(fn.saturation, {}, [ArgCb("saturation", saturation, True)]),
(fn.hsv, {}, [ArgCb("hue", hue, True), ArgCb(
Copy link
Contributor

Choose a reason for hiding this comment

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

hue hue :D

@stiepan stiepan force-pushed the per_frame_brightness_contrast branch from 86efd70 to ad0b697 Compare June 1, 2022 18:53
@stiepan
Copy link
Member Author

stiepan commented Jun 1, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4987616]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4987616]: BUILD FAILED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [4987616]: BUILD PASSED

@stiepan stiepan force-pushed the per_frame_brightness_contrast branch from ad0b697 to ba96ce9 Compare June 6, 2022 08:45
@stiepan
Copy link
Member Author

stiepan commented Jun 6, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5023066]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5023066]: BUILD PASSED

@stiepan stiepan requested a review from klecki June 6, 2022 13:00
@stiepan stiepan force-pushed the per_frame_brightness_contrast branch from ba96ce9 to f3762f5 Compare June 14, 2022 12:45
@stiepan
Copy link
Member Author

stiepan commented Jun 14, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5081203]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5081203]: BUILD PASSED

@stiepan
Copy link
Member Author

stiepan commented Jun 14, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5081892]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5081892]: BUILD PASSED

@stiepan stiepan merged commit e687379 into NVIDIA:main Jun 14, 2022
@JanuszL JanuszL mentioned this pull request Jan 11, 2023
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