I was following this blog and was trying to replace a dynamic polymorphism code into using std::variant
and std::visit
. But I can not get std::variant
+ std::visit
to work better than a virtual struct impl. Its about 1.3-1.5x slower! (GCC 10.3 -O3 C++17)
The use case is as follows. Say we are comparing i'th and j'th row of two tables. A table could have heterogeneously typed columns. Assume we can access column buffers. What I am doing is testing,
def IndexEqual(Table:A, Table:B, int:i, int:j):
for c in range(A.num_cols):
if not A.column(c)[i] == B.column(c)[j]:
return False
return True
for dynamic polymorphism I have the following for int
and float
struct Comp{
virtual bool comp(size_t i, size_t j) const = 0;
};
struct CompI: public Comp {
CompI(const int *data_1, const int *data_2) : data1(data_1), data2(data_2) {}
const int *data1, *data2;
bool comp(size_t i, size_t j) const override {
return data1[i] == data2[j];
}
};
struct CompF: public Comp {
CompF(const float *data_1, const float *data_2) : data1(data_1), data2(data_2) {}
const float *data1, *data2;
bool comp(size_t i, size_t j) const override {
return data1[i] == data2[j];
}
};
bool IndexEqual1(const std::vector<Comp *> &comps, size_t i, size_t j) {
for (auto &&a: comps) {
if (!a->comp(i, j)) {
return false;
}
}
return true;
}
This was transformed to std::variant
+ std::visit
as follows.
struct EqualToI {
EqualToI(const int *data_1, const int *data_2) : data1(data_1), data2(data_2) {}
const int *data1, *data2;
bool comp(size_t i, size_t j) const {
return data1[i] == data2[j];
}
};
struct EqualToF {
EqualToF(const float *data_1, const float *data_2) : data1(data_1), data2(data_2) {}
const float *data1, *data2;
bool comp(size_t i, size_t j) const {
return data1[i] == data2[j];
}
};
using var_type = typename std::variant<EqualToI, EqualToF>;
bool IndexEqual(const std::vector<var_type> &comps, size_t i, size_t j) {
for (auto &&a: comps) {
if (!std::visit([&](const auto &comp) {
return comp.comp(i, j);
}, a)) {
return false;
}
}
return true;
}
I benchmarked this here https://quick-bench.com/q/u-cBjg4hyQjOs6fKem9XSdW7LMs
Can someone one please explain why this std::variant
+ std::visit
option is slower than the dynamic polimorphism approach? I was expecting otherwise! Is there a problem in my approach and/or benchmark?