1
0

Add Block-Allocation of lst pointers

Profiling revealed significant performance overhead in using std::shared_ptr for lst.

There is even significant overhead in using new for lst.

Using pointers to blocks of pre-allocated memory for lst drastically improves performance (about 50%).

E7 and E8 show this well, since they allocate many lst pointers.

With shared_ptr: E7 ~3.3s, B8 ~21s.

With BlockAllocator: E7 ~1.6s, B8 ~11s.
This commit is contained in:
David Allemang
2021-11-01 11:23:17 -04:00
parent 68065f4a56
commit d36b03b4f9

View File

@@ -42,7 +42,7 @@ namespace tc {
namespace {
struct Row {
int gnr;
std::shared_ptr<int> lst;
int *lst;
};
struct Table {
@@ -56,13 +56,46 @@ namespace {
}
};
template<class T, size_t BlockSize = 4096>
class BlockAllocator {
/// 4096 seems to be the best (on my machine anway) from profiling.
private:
int block = 0;
int next = 0;
std::vector<T *> data = {build()};
T *build() {
T *blk = new T[BlockSize];
std::fill_n(blk, BlockSize, 0);
return blk;
}
public:
T *operator()() {
if (next >= BlockSize) {
data.push_back(build());
block++;
next = 0;
}
return &data[block][next++];
}
~BlockAllocator() {
for (auto &blk: data) {
delete[] blk;
}
}
};
template<unsigned int Rank>
class Tables {
public:
static constexpr unsigned int Rels = Rank * (Rank + 1) / 2 - Rank;
private:
std::shared_ptr<int> null_lst_ptr = std::make_shared<int>();
int *null_lst_ptr = new int;
BlockAllocator<int> alloc;
std::array<std::shared_ptr<Table>, Rels> tables;
std::array<std::vector<std::shared_ptr<Table>>, Rank> deps;
@@ -94,7 +127,7 @@ namespace {
if (row.lst == nullptr) {
if (cosets.get(target, rel.gens[0]) != target and
cosets.get(target, rel.gens[1]) != target) {
row.lst = std::make_shared<int>();
row.lst = alloc();
row.gnr = 0;
} else {
row.lst = null_lst_ptr;
@@ -104,6 +137,10 @@ namespace {
}
}
~Tables() {
delete null_lst_ptr;
}
void learn(int coset, int gen, int target, const tc::Cosets &cosets, std::priority_queue<int> &facts) {
if (target == coset) {
for (auto &table: deps[gen]) {