This is an archive of the discontinued LLVM Phabricator instance.

[NFC][lsan] Avoid O(N^2) algorithm
ClosedPublic

Authored by vitalybuka on May 30 2023, 11:02 PM.

Details

Summary

Usually root_regions size is small so unlikey
this change will provide a noticable difference.

However it's easy to make sure that even with
large number of root_regions it works reasonably
fast.

Diff Detail

Event Timeline

vitalybuka created this revision.May 30 2023, 11:02 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 30 2023, 11:02 PM
Herald added a subscriber: Enna1. · View Herald Transcript
vitalybuka requested review of this revision.May 30 2023, 11:02 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 30 2023, 11:02 PM
Herald added a subscriber: Restricted Project. · View Herald Transcript
vitalybuka retitled this revision from [NFC][sanitizer] Avoid O(N^2) algorithm to [NFC][lsan] Avoid O(N^2) algorithm.

D151779 added an interaction algorithm of two region lists using a scan line algorithm. The algorithm needs to maintain a sorted event array.

This problem has a property that the second region list (mapped_regions) is sorted and the first region list (root_regions) can be sorted in place.
I think we can open code a specialized version of the interaction algorithm just in lib/lsan, similar to merging two sorted list, with a space complexity of O(1).

D151779 added an interaction algorithm of two region lists using a scan line algorithm. The algorithm needs to maintain a sorted event array.

This problem has a property that the second region list (mapped_regions) is sorted and the first region list (root_regions) can be sorted in place.
I think we can open code a specialized version of the interaction algorithm just in lib/lsan, similar to merging two sorted list, with a space complexity of O(1).

I don't realy concerned with space complexity here.
Seems like D151779 is simple, general and good enough to solve the proplem.

MaskRay added a comment.EditedMay 31 2023, 12:57 PM

D151779 added an interaction algorithm of two region lists using a scan line algorithm. The algorithm needs to maintain a sorted event array.

This problem has a property that the second region list (mapped_regions) is sorted and the first region list (root_regions) can be sorted in place.
I think we can open code a specialized version of the interaction algorithm just in lib/lsan, similar to merging two sorted list, with a space complexity of O(1).

I don't realy concerned with space complexity here.
Seems like D151779 is simple, general and good enough to solve the proplem.

Yes, it's simple enough, but a merge style algorithm for intersection will be simpler :)

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <utility>
#include <vector>
using namespace std;

vector<pair<int, int>> intersect(vector<pair<int, int>> &a, const vector<pair<int, int>> &b) {
  assert(is_sorted(a.begin(), a.end()));
  assert(is_sorted(b.begin(), b.end()));
  vector<pair<int, int>> ret;
  auto ia = a.begin();
  auto ib = b.begin();
  while (ia != a.end() && ib != b.end()) {
    // We don't merge [10,12) [12,14) into [10,14), but ScanRangeForPointers is happy with that.
    auto l = max(ia->first, ib->first);
    auto r = min(ia->second, ib->second);
    if (l < r)
      ret.emplace_back(l, r);
    if (ia->second < ib->second)
      ++ia;
    else
      ++ib;
  }
  return ret;
}

int main() {
  vector<pair<int, int>> a{{1,2}, {2,4}, {5,8}, {10,12}, {12,14}, {14, 16}};
  vector<pair<int, int>> b{{1,5}, {6,7}, {7,9}, {10,12}, {12,14}, {14, 16}};
  for (auto x : intersect(a, b))
    printf("[%d, %d)\n", x.first, x.second);
}

D151779 added an interaction algorithm of two region lists using a scan line algorithm. The algorithm needs to maintain a sorted event array.

This problem has a property that the second region list (mapped_regions) is sorted and the first region list (root_regions) can be sorted in place.
I think we can open code a specialized version of the interaction algorithm just in lib/lsan, similar to merging two sorted list, with a space complexity of O(1).

I don't realy concerned with space complexity here.
Seems like D151779 is simple, general and good enough to solve the proplem.

Yes, it's simple enough, but a merge style algorithm for intersection will be simpler :)

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <utility>
#include <vector>
using namespace std;

vector<pair<int, int>> intersect(vector<pair<int, int>> &a, const vector<pair<int, int>> &b) {
  assert(is_sorted(a.begin(), a.end()));
  assert(is_sorted(b.begin(), b.end()));
  vector<pair<int, int>> ret;
  auto ia = a.begin();
  auto ib = b.begin();
  while (ia != a.end() && ib != b.end()) {
    // We don't merge [10,12) [12,14) into [10,14), but ScanRangeForPointers is happy with that.

This is not general^, and unnecessary rely on user behavior.

  auto l = max(ia->first, ib->first);
  auto r = min(ia->second, ib->second);
  if (l < r)
    ret.emplace_back(l, r);
  if (ia->second < ib->second)
    ++ia;
  else
    ++ib;
}
return ret;

}

int main() {

vector<pair<int, int>> a{{1,2}, {2,4}, {5,8}, {10,12}, {12,14}, {14, 16}};
vector<pair<int, int>> b{{1,5}, {6,7}, {7,9}, {10,12}, {12,14}, {14, 16}};
for (auto x : intersect(a, b))
  printf("[%d, %d)\n", x.first, x.second);

}

It's not complicated, but it need some time to realize if this will handled overlapping regions in one of inputs (seems it will not).

also it's going to be annoying to templatize to support XOR or AND version if needed.

MaskRay accepted this revision.Jun 1 2023, 7:03 AM
This revision is now accepted and ready to land.Jun 1 2023, 7:03 AM
This revision was landed with ongoing or failed builds.Jun 2 2023, 2:32 PM
This revision was automatically updated to reflect the committed changes.