-
Notifications
You must be signed in to change notification settings - Fork 529
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
fix memory leak in regions(cpu backend) & rgb2ycbcr(api level) #1666
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
|
||
#pragma once | ||
#include <Array.hpp> | ||
#include <memory.hpp> | ||
|
||
namespace cpu | ||
{ | ||
|
@@ -98,78 +99,77 @@ static void setUnion(LabelNode<T>* x, LabelNode<T>* y) | |
template<typename T> | ||
void regions(Array<T> out, const Array<char> in, af_connectivity connectivity) | ||
{ | ||
const af::dim4 in_dims = in.dims(); | ||
const char *in_ptr = in.get(); | ||
T *out_ptr = out.get(); | ||
const af::dim4 inDims = in.dims(); | ||
const char *inPtr = in.get(); | ||
T *outPtr = out.get(); | ||
|
||
// Map labels | ||
typedef typename std::map<T, LabelNode<T>* > label_map_t; | ||
typedef typename label_map_t::iterator label_map_iterator_t; | ||
typedef typename std::unique_ptr< LabelNode<T> > UnqLabelPtr; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use consistent naming conventions within a file. |
||
typedef typename std::map<T, UnqLabelPtr > LabelMap; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only used once. It is an unnecessary indirection but not a big deal. Your call Also. Use the using keyword for type aliasing. They are easier to read and more powerful.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just one character smaller.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's easier (for me) to read because it uses the assignment style to define the alias, not because it is shorter. |
||
typedef typename LabelMap::iterator LabelMapIterator; | ||
|
||
label_map_t lmap; | ||
LabelMap lmap; | ||
|
||
// Initial label | ||
T label = (T)1; | ||
|
||
for (int j = 0; j < (int)in_dims[1]; j++) { | ||
for (int i = 0; i < (int)in_dims[0]; i++) { | ||
int idx = j * in_dims[0] + i; | ||
if (in_ptr[idx] != 0) { | ||
for (int j = 0; j < (int)inDims[1]; j++) { | ||
for (int i = 0; i < (int)inDims[0]; i++) { | ||
int idx = j * inDims[0] + i; | ||
if (inPtr[idx] != 0) { | ||
std::vector<T> l; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be better if this was a std::array instead of a std::vector. Since std::arrays are allocated on the stack, you don't get the penalty of calling malloc. I know its not part of this PR. Perhaps in another issue. |
||
|
||
// Test neighbors | ||
if (i > 0 && out_ptr[j * (int)in_dims[0] + i-1] > 0) | ||
l.push_back(out_ptr[j * in_dims[0] + i-1]); | ||
if (j > 0 && out_ptr[(j-1) * (int)in_dims[0] + i] > 0) | ||
l.push_back(out_ptr[(j-1) * in_dims[0] + i]); | ||
if (i > 0 && outPtr[j * (int)inDims[0] + i-1] > 0) | ||
l.push_back(outPtr[j * inDims[0] + i-1]); | ||
if (j > 0 && outPtr[(j-1) * (int)inDims[0] + i] > 0) | ||
l.push_back(outPtr[(j-1) * inDims[0] + i]); | ||
if (connectivity == AF_CONNECTIVITY_8 && i > 0 && | ||
j > 0 && out_ptr[(j-1) * in_dims[0] + i-1] > 0) | ||
l.push_back(out_ptr[(j-1) * in_dims[0] + i-1]); | ||
j > 0 && outPtr[(j-1) * inDims[0] + i-1] > 0) | ||
l.push_back(outPtr[(j-1) * inDims[0] + i-1]); | ||
if (connectivity == AF_CONNECTIVITY_8 && | ||
i < (int)in_dims[0] - 1 && j > 0 && out_ptr[(j-1) * in_dims[0] + i+1] != 0) | ||
l.push_back(out_ptr[(j-1) * in_dims[0] + i+1]); | ||
i < (int)inDims[0] - 1 && j > 0 && outPtr[(j-1) * inDims[0] + i+1] != 0) | ||
l.push_back(outPtr[(j-1) * inDims[0] + i+1]); | ||
|
||
if (!l.empty()) { | ||
T minl = l[0]; | ||
for (size_t k = 0; k < l.size(); k++) { | ||
minl = min(l[k], minl); | ||
label_map_iterator_t cur_map = lmap.find(l[k]); | ||
LabelNode<T> *node = cur_map->second; | ||
LabelMapIterator currentMap = lmap.find(l[k]); | ||
LabelNode<T> *node = currentMap->second.get(); | ||
// Group labels of the same region under a disjoint set | ||
for (size_t m = k+1; m < l.size(); m++) | ||
setUnion(node, lmap.find(l[m])->second); | ||
setUnion(node, lmap.find(l[m])->second.get()); | ||
} | ||
// Set label to smallest neighbor label | ||
out_ptr[idx] = minl; | ||
} | ||
else { | ||
outPtr[idx] = minl; | ||
} else { | ||
// Insert new label in map | ||
LabelNode<T> *node = new LabelNode<T>(label); | ||
lmap.insert(std::pair<T, LabelNode<T>* >(label, node)); | ||
out_ptr[idx] = label++; | ||
lmap.insert(std::make_pair(label, UnqLabelPtr(new LabelNode<T>(label)))); | ||
outPtr[idx] = label++; | ||
} | ||
} | ||
} | ||
} | ||
|
||
std::set<T> removed; | ||
|
||
for (int j = 0; j < (int)in_dims[1]; j++) { | ||
for (int i = 0; i < (int)in_dims[0]; i++) { | ||
int idx = j * (int)in_dims[0] + i; | ||
if (in_ptr[idx] != 0) { | ||
T l = out_ptr[idx]; | ||
label_map_iterator_t cur_map = lmap.find(l); | ||
for (int j = 0; j < (int)inDims[1]; j++) { | ||
for (int i = 0; i < (int)inDims[0]; i++) { | ||
int idx = j * (int)inDims[0] + i; | ||
if (inPtr[idx] != 0) { | ||
T l = outPtr[idx]; | ||
LabelMapIterator currentMap = lmap.find(l); | ||
|
||
if (cur_map != lmap.end()) { | ||
LabelNode<T>* node = cur_map->second; | ||
if (currentMap != lmap.end()) { | ||
LabelNode<T>* node = currentMap->second.get(); | ||
|
||
LabelNode<T>* node_root = find(node); | ||
out_ptr[idx] = node_root->getMinLabel(); | ||
LabelNode<T>* nodeRoot = find(node); | ||
outPtr[idx] = nodeRoot->getMinLabel(); | ||
|
||
// Mark removed labels (those that are part of a region | ||
// that contains a smaller label) | ||
if (node->getMinLabel() < l || node_root->getMinLabel() < l) | ||
if (node->getMinLabel() < l || nodeRoot->getMinLabel() < l) | ||
removed.insert(l); | ||
if (node->getLabel() > node->getMinLabel()) | ||
removed.insert(node->getLabel()); | ||
|
@@ -179,11 +179,11 @@ void regions(Array<T> out, const Array<char> in, af_connectivity connectivity) | |
} | ||
|
||
// Calculate final neighbors (ensure final labels are sequential) | ||
for (int j = 0; j < (int)in_dims[1]; j++) { | ||
for (int i = 0; i < (int)in_dims[0]; i++) { | ||
int idx = j * (int)in_dims[0] + i; | ||
if (out_ptr[idx] > 0) { | ||
out_ptr[idx] -= distance(removed.begin(), removed.lower_bound(out_ptr[idx])); | ||
for (int j = 0; j < (int)inDims[1]; j++) { | ||
for (int i = 0; i < (int)inDims[0]; i++) { | ||
int idx = j * (int)inDims[0] + i; | ||
if (outPtr[idx] > 0) { | ||
outPtr[idx] -= distance(removed.begin(), removed.lower_bound(outPtr[idx])); | ||
} | ||
} | ||
} | ||
|
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.
If you are making another commit in this PR, can you add a comment saying why you are only assigning to
indices[2]
in all the 3 cases. I think it would help code readability.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.
@shehzan10 Because he is reading the three channels into 3 different arrays ?
@9prady9 Can you check if something like
createSubArray(input, {af_span, af_span, {1,1,1}}, false);
works.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 have left comments before the beginning of extraction of channels. In any case, i don't have any other commits left in this PR.
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 know why he is doing it, but it took me a bit to realize it. That's why I said "if you are making another commit", because its not that much of a priority. It just helps anyone in the future who is going to read 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.
@pavanky I checked by running the existing tests, why would we need copy's of original Array ? Just indexed Array's are sufficient right ?
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.
Is there a possibility that the meta-data may not be properly altered ?
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.
@9prady9 Check my comment again. I did not say anything about copy, I was wondering if array initializers work instead of using vectors.