【发布时间】:2021-03-02 14:53:39
【问题描述】:
我正在尝试根据图像分类的结果尽可能快地构建一组元素。
在细节上,我想在这个集合中存储属于某个类的所有 (r, g, b) 像素。问题有 2 个类,我想保留 1 类的像素并丢弃 0 类的像素。
分类是使用经过训练的 mlpack 分类器在双精度 (r, g, b) 向量上完成的。
我必须使用 boost::unordered_set<uint32_t> 来完成此任务或类似任务。
到现在为止的代码是这样的
boost::unordered_set<uint32_t> bset;
for (int r = 0; r < 256; r++)
{
for (int g = 0; g < 256; g++)
{
for (int b = 0; b < 256; b++)
{
arma::rowvec xp = { (double)b, (double)g, (double)r };
if ((bool)(clf.Classify(xp))) {
uint32_t cachePos = r + (g << 8) + (b << 16);
bset.insert(cachePos);
}
}
}
}
我做了一些基准测试,最慢的部分是插入insert()。扫描所有可能的 (r, g, b) 大约需要 5 秒。由于代码是从 GUI 调用的,因此我希望它更快,以减少用户等待结果的时间。
首先,我尝试将.insert() 更改为.emplace(),但正如我所料,几乎没有改进。
我也尝试填充另一个容器,实际上std::vector 非常快,并且使用迭代器将其内容复制到集合中:
std::vector<int> predictions;
for (int r = 0; r < 256; r++)
{
for (int g = 0; g < 256; g++)
{
for (int b = 0; b < 256; b++)
{
arma::rowvec xp = { (double)b, (double)g, (double)r };
if ((bool)(clf.Classify(xp))) {
uint32_t cachePos = r + (g << 8) + (b << 16);
predictions.push_back(cachePos);
}
}
}
}
bset = boost::unordered_set<uint32_t>(predictions.begin(), predictions.end());
但是,最后一行仍然需要很长时间,大约 2-3 秒。你对我有什么暗示吗?
我可以做些什么来提高我的代码速度?是否有更快的容器可以用来替换 boost::unordered_set ?容器应仅包含来自第 1 类的元素。
【问题讨论】:
-
最后一定要存到
boost::unordered_set吗?std::bitset可能是一个选项。 -
集合的最终尺寸是多少?每次我做基准比较
std::set和std::unordered_set时,我发现第一个更快。但我没有用无限大小进行这些测试!我将这些测试的大小限制为 10^7。 -
@Jarod42 我不能使用 std::bitset 因为设置的大小可以改变。但我尝试了
boost::dynamic_bitset,它非常快。关键是(据我所知)bitset 是一组 0 和 1。我不知道如何存储所有且仅存储 1 类的 (r, g, b) 。你会怎么做?当我找到 1 类的成员时,我不能只是 push_back -
@Damien 我没有尝试
std::set,但这是一个想法!正如我上面回答的那样,大小不是固定的。这取决于分类的结果。此外,该集合作为对使用我发布的代码的函数的引用传递,有时会在它之外进行修改。 -
请注意,通过修改循环的顺序,您将得到一个已排序的
vector。我不知道您是否可以简单地使用这个有序数组。如果没有,它可能有助于快速创建一个std::set,以供检查。
标签: c++ boost containers mlpack boost-unordered