Skip to content

Commit 20da032

Browse files
committed
Add experimental CV-CUDA resize
Signed-off-by: Rafal Banas <[email protected]>
1 parent bdcf160 commit 20da032

File tree

14 files changed

+717
-61
lines changed

14 files changed

+717
-61
lines changed

cmake/Dependencies.common.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ if (BUILD_CVCUDA)
264264
set(DALI_BUILD_PYTHON ${BUILD_PYTHON})
265265
set(BUILD_PYTHON OFF)
266266
# for now we use only median blur from CV-CUDA
267-
set(CV_CUDA_SRC_PATERN medianblur median_blur morphology warp)
267+
set(CV_CUDA_SRC_PATERN medianblur median_blur morphology warp HQResize)
268268
check_and_add_cmake_submodule(${PROJECT_SOURCE_DIR}/third_party/cvcuda)
269269
set(BUILD_PYTHON ${DALI_BUILD_PYTHON})
270270
endif()

dali/operators/image/resize/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
1+
# Copyright (c) 2017-2024, NVIDIA CORPORATION. All rights reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -12,7 +12,12 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
if (BUILD_CVCUDA)
16+
add_subdirectory(experimental)
17+
endif()
18+
1519
# Get all the source files and dump test files
1620
collect_headers(DALI_INST_HDRS PARENT_SCOPE)
1721
collect_sources(DALI_OPERATOR_SRCS PARENT_SCOPE)
1822
collect_test_sources(DALI_OPERATOR_TEST_SRCS PARENT_SCOPE)
23+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
collect_headers(DALI_INST_HDRS PARENT_SCOPE)
17+
collect_sources(DALI_OPERATOR_SRCS PARENT_SCOPE)
18+
collect_test_sources(DALI_OPERATOR_TEST_SRCS PARENT_SCOPE)
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#define DALI_RESIZE_BASE_CC
16+
17+
#include "dali/operators/image/resize/experimental/resize.h"
18+
#include <cassert>
19+
#include "dali/pipeline/data/views.h"
20+
21+
namespace dali {
22+
23+
DALI_SCHEMA(experimental__Resize)
24+
.DocStr(R"code(Resize images.)code")
25+
.NumInput(1)
26+
.NumOutput(1)
27+
.AdditionalOutputsFn([](const OpSpec& spec) {
28+
return static_cast<int>(spec.GetArgument<bool>("save_attrs"));
29+
})
30+
.InputLayout(0, {"HWC", "FHWC", "CHW", "FCHW", "CFHW" ,
31+
"DHWC", "FDHWC", "CDHW", "FCDHW", "CFDHW" })
32+
.AddOptionalArg("save_attrs",
33+
R"code(Save reshape attributes for testing.)code", false)
34+
.AddOptionalArg<DALIImageType>("image_type", "Image type", nullptr)
35+
.DeprecateArg("image_type") // deprecated since 0.25dev
36+
.SupportVolumetric()
37+
.AllowSequences()
38+
.AddParent("ResizeAttr")
39+
.AddParent("ResamplingFilterAttr");
40+
41+
CvCudaResize::CvCudaResize(const OpSpec &spec)
42+
: StatelessOperator<GPUBackend>(spec)
43+
, ResizeBase<GPUBackend>(spec) {
44+
save_attrs_ = this->spec_.HasArgument("save_attrs");
45+
InitializeBackend();
46+
}
47+
48+
void CvCudaResize::InitializeBackend() {
49+
InitializeGPU(spec_.GetArgument<int>("minibatch_size"),
50+
spec_.GetArgument<int64_t>("temp_buffer_hint"));
51+
}
52+
53+
void CvCudaResize::RunImpl(Workspace &ws) {
54+
const auto &input = ws.Input<GPUBackend>(0);
55+
auto &output = ws.Output<GPUBackend>(0);
56+
57+
RunResize(ws, output, input);
58+
output.SetLayout(input.GetLayout());
59+
60+
if (save_attrs_) {
61+
auto &attr_out = ws.Output<GPUBackend>(1);
62+
const auto &attr_shape = attr_out.shape();
63+
assert(attr_shape.num_samples() == input.shape().num_samples() &&
64+
attr_shape.sample_dim() == 1 &&
65+
is_uniform(attr_shape) &&
66+
attr_shape[0][0] == NumSpatialDims());
67+
68+
if (!attr_staging_.has_data())
69+
attr_staging_.set_pinned(true);
70+
attr_staging_.Resize(attr_out.shape(), DALI_INT32);
71+
auto attr_view = view<int, 1>(attr_staging_);
72+
SaveAttrs(attr_view, input.shape());
73+
attr_out.Copy(attr_staging_, ws.stream());
74+
}
75+
}
76+
77+
DALI_REGISTER_OPERATOR(experimental__Resize, CvCudaResize, GPU);
78+
79+
} // namespace dali
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef DALI_OPERATORS_IMAGE_RESIZE_EXPERIMENTAL_RESIZE_H_
16+
#define DALI_OPERATORS_IMAGE_RESIZE_EXPERIMENTAL_RESIZE_H_
17+
18+
#include <random>
19+
#include <utility>
20+
#include <vector>
21+
#include <memory>
22+
23+
#include "dali/core/common.h"
24+
#include "dali/core/error_handling.h"
25+
#include "dali/kernels/context.h"
26+
#include "dali/kernels/imgproc/resample/params.h"
27+
#include "dali/kernels/scratch.h"
28+
#include "dali/operators/image/resize/experimental/resize_op_impl_cvcuda.h"
29+
#include "dali/operators/image/resize/resize_attr.h"
30+
#include "dali/operators/image/resize/resize_base.h"
31+
#include "dali/pipeline/operator/checkpointing/stateless_operator.h"
32+
#include "dali/pipeline/operator/common.h"
33+
34+
namespace dali {
35+
36+
class CvCudaResize : public StatelessOperator<GPUBackend>, protected ResizeBase<GPUBackend> {
37+
public:
38+
explicit CvCudaResize(const OpSpec &spec);
39+
40+
protected:
41+
void SetupResize(TensorListShape<> &out_shape, DALIDataType out_type,
42+
const TensorListShape<> &in_shape, DALIDataType in_type,
43+
span<const kernels::ResamplingParams> params, int spatial_ndim,
44+
int first_spatial_dim) {
45+
VALUE_SWITCH(spatial_ndim, static_spatial_ndim, (2, 3),
46+
(
47+
using ImplType = ResizeOpImplCvCuda<static_spatial_ndim>;
48+
SetImpl<ImplType>([&]{ return std::make_unique<ImplType>(GetMinibatchSize()); });
49+
impl_->Setup(out_shape, in_shape, first_spatial_dim, params);
50+
), // NOLINT
51+
(DALI_FAIL(make_string("Unsupported number of resized dimensions: ", spatial_ndim))));
52+
}
53+
54+
55+
int NumSpatialDims() const {
56+
return resize_attr_.spatial_ndim_;
57+
}
58+
int FirstSpatialDim() const {
59+
return resize_attr_.first_spatial_dim_;
60+
}
61+
62+
bool CanInferOutputs() const override {
63+
return true;
64+
}
65+
66+
bool SetupImpl(std::vector<OutputDesc> &output_desc, const Workspace &ws) override;
67+
68+
void RunImpl(Workspace &ws) override;
69+
70+
void SaveAttrs(const TensorListView<StorageCPU, int, 1> &shape_data,
71+
const TensorListShape<> &orig_shape) const {
72+
int N = orig_shape.num_samples();
73+
int D = NumSpatialDims();
74+
assert(shape_data.sample_dim() == 1);
75+
for (int i = 0; i < N; i++) {
76+
auto sample_shape = orig_shape.tensor_shape_span(i);
77+
assert(static_cast<int>(shape_data.shape[i][0]) == D);
78+
int *out_shape = shape_data.data[i];
79+
for (int d = 0; d < D; d++) {
80+
out_shape[d] = sample_shape[FirstSpatialDim() + d];
81+
}
82+
}
83+
}
84+
85+
void PrepareParams(const ArgumentWorkspace &ws, const TensorListShape<> &input_shape,
86+
const TensorLayout &layout) {
87+
resize_attr_.PrepareResizeParams(spec_, ws, input_shape, layout);
88+
assert(NumSpatialDims() >= 1 && NumSpatialDims() <= 3);
89+
assert(FirstSpatialDim() >= 0);
90+
int N = input_shape.num_samples();
91+
resample_params_.resize(N * NumSpatialDims());
92+
resampling_attr_.PrepareFilterParams(spec_, ws, N);
93+
resampling_attr_.GetResamplingParams(make_span(resample_params_),
94+
make_cspan(resize_attr_.params_));
95+
}
96+
97+
void InitializeBackend();
98+
99+
USE_OPERATOR_MEMBERS();
100+
std::vector<kernels::ResamplingParams> resample_params_;
101+
TensorList<CPUBackend> attr_staging_;
102+
using Operator<GPUBackend>::RunImpl;
103+
bool save_attrs_ = false;
104+
105+
ResizeAttr resize_attr_;
106+
ResamplingFilterAttr resampling_attr_;
107+
};
108+
109+
bool CvCudaResize::SetupImpl(std::vector<OutputDesc> &output_desc, const Workspace &ws) {
110+
output_desc.resize(save_attrs_ ? 2 : 1);
111+
auto &input = ws.Input<GPUBackend>(0);
112+
113+
const auto &in_shape = input.shape();
114+
auto in_type = input.type();
115+
auto in_layout = input.GetLayout();
116+
int N = in_shape.num_samples();
117+
118+
PrepareParams(ws, in_shape, in_layout);
119+
120+
auto out_type = resampling_attr_.GetOutputType(in_type);
121+
122+
output_desc[0].type = out_type;
123+
this->SetupResize(output_desc[0].shape, out_type, in_shape, in_type,
124+
make_cspan(this->resample_params_), NumSpatialDims(), FirstSpatialDim());
125+
126+
if (save_attrs_) {
127+
output_desc[1].shape = uniform_list_shape(N, TensorShape<1>({NumSpatialDims()}));
128+
output_desc[1].type = DALI_INT32;
129+
}
130+
return true;
131+
}
132+
133+
} // namespace dali
134+
135+
#endif // DALI_OPERATORS_IMAGE_RESIZE_EXPERIMENTAL_RESIZE_H_

0 commit comments

Comments
 (0)