Skip to content

Commit 4d4c10a

Browse files
authored
[Enhancement] Avoid copying dense arrays in Python API (#1349)
* eliminate copying for segmentor * fix segmentor * eliminate copying in Python API * minor fix
1 parent 73e095a commit 4d4c10a

File tree

3 files changed

+34
-22
lines changed

3 files changed

+34
-22
lines changed

csrc/mmdeploy/apis/python/detector.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,16 @@ class PyDetector {
2828
if (status != MMDEPLOY_SUCCESS) {
2929
throw std::runtime_error("failed to apply detector, code: " + std::to_string(status));
3030
}
31+
using Sptr = std::shared_ptr<mmdeploy_detection_t>;
32+
Sptr holder(detection, [result_count, n = mats.size()](auto p) {
33+
mmdeploy_detector_release_result(p, result_count, n);
34+
});
3135
auto output = py::list{};
3236
auto result = detection;
3337
for (int i = 0; i < mats.size(); ++i) {
3438
auto bboxes = py::array_t<float>({result_count[i], 5});
3539
auto labels = py::array_t<int>(result_count[i]);
36-
auto masks = std::vector<py::array_t<uint8_t>>{};
40+
auto masks = std::vector<py::array>();
3741
masks.reserve(result_count[i]);
3842
for (int j = 0; j < result_count[i]; ++j, ++result) {
3943
auto bbox = bboxes.mutable_data(j);
@@ -44,16 +48,16 @@ class PyDetector {
4448
bbox[4] = result->score;
4549
labels.mutable_at(j) = result->label_id;
4650
if (result->mask) {
47-
py::array_t<uint8_t> mask({result->mask->height, result->mask->width});
48-
memcpy(mask.mutable_data(), result->mask->data, mask.nbytes());
49-
masks.push_back(std::move(mask));
51+
masks.emplace_back(std::array{result->mask->height, result->mask->width}, // shape
52+
reinterpret_cast<uint8_t*>(result->mask->data), // data
53+
py::capsule(new Sptr(holder), // handle
54+
[](void* p) { delete reinterpret_cast<Sptr*>(p); }));
5055
} else {
5156
masks.emplace_back();
5257
}
5358
}
5459
output.append(py::make_tuple(std::move(bboxes), std::move(labels), std::move(masks)));
5560
}
56-
mmdeploy_detector_release_result(detection, result_count, (int)mats.size());
5761
return output;
5862
}
5963
~PyDetector() {

csrc/mmdeploy/apis/python/restorer.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class PyRestorer {
1919
restorer_ = {};
2020
}
2121

22-
std::vector<py::array_t<uint8_t>> Apply(const std::vector<PyImage>& imgs) {
22+
std::vector<py::array> Apply(const std::vector<PyImage>& imgs) {
2323
std::vector<mmdeploy_mat_t> mats;
2424
mats.reserve(imgs.size());
2525
for (const auto& img : imgs) {
@@ -31,15 +31,19 @@ class PyRestorer {
3131
if (status != MMDEPLOY_SUCCESS) {
3232
throw std::runtime_error("failed to apply restorer, code: " + std::to_string(status));
3333
}
34-
auto output = std::vector<py::array_t<uint8_t>>{};
35-
output.reserve(mats.size());
34+
using Sptr = std::shared_ptr<mmdeploy_mat_t>;
35+
Sptr holder(results, [n = mats.size()](auto p) { mmdeploy_restorer_release_result(p, n); });
36+
37+
std::vector<py::array> rets(mats.size());
3638
for (int i = 0; i < mats.size(); ++i) {
37-
py::array_t<uint8_t> restored({results[i].height, results[i].width, results[i].channel});
38-
memcpy(restored.mutable_data(), results[i].data, restored.nbytes());
39-
output.push_back(std::move(restored));
39+
rets[i] = {
40+
{results[i].height, results[i].width, results[i].channel}, // shape
41+
results[i].data, // data
42+
py::capsule(new Sptr(holder), // handle
43+
[](void* p) { delete reinterpret_cast<Sptr*>(p); }) //
44+
};
4045
}
41-
mmdeploy_restorer_release_result(results, (int)mats.size());
42-
return output;
46+
return rets;
4347
}
4448

4549
private:

csrc/mmdeploy/apis/python/segmentor.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class PySegmentor {
2020
segmentor_ = {};
2121
}
2222

23-
std::vector<py::array_t<int>> Apply(const std::vector<PyImage>& imgs) {
23+
std::vector<py::array> Apply(const std::vector<PyImage>& imgs) {
2424
std::vector<mmdeploy_mat_t> mats;
2525
mats.reserve(imgs.size());
2626
for (const auto& img : imgs) {
@@ -32,15 +32,19 @@ class PySegmentor {
3232
if (status != MMDEPLOY_SUCCESS) {
3333
throw std::runtime_error("failed to apply segmentor, code: " + std::to_string(status));
3434
}
35-
auto output = std::vector<py::array_t<int>>{};
36-
output.reserve(mats.size());
37-
for (int i = 0; i < mats.size(); ++i) {
38-
auto mask = py::array_t<int>({segm[i].height, segm[i].width});
39-
memcpy(mask.mutable_data(), segm[i].mask, mask.nbytes());
40-
output.push_back(std::move(mask));
35+
using Sptr = std::shared_ptr<mmdeploy_segmentation_t>;
36+
Sptr holder(segm, [n = mats.size()](auto p) { mmdeploy_segmentor_release_result(p, n); });
37+
38+
std::vector<py::array> rets(mats.size());
39+
for (size_t i = 0; i < mats.size(); ++i) {
40+
rets[i] = {
41+
{segm[i].height, segm[i].width}, // shape
42+
segm[i].mask, // data
43+
py::capsule(new Sptr(holder), // handle
44+
[](void* p) { delete reinterpret_cast<Sptr*>(p); }) //
45+
};
4146
}
42-
mmdeploy_segmentor_release_result(segm, (int)mats.size());
43-
return output;
47+
return rets;
4448
}
4549

4650
private:

0 commit comments

Comments
 (0)