执行数千次比较的最快方法

Posted

技术标签:

【中文标题】执行数千次比较的最快方法【英文标题】:Fastest way to perform thousands of comparisons 【发布时间】:2014-06-23 16:08:09 【问题描述】:

我正在研究将 RGB 颜色转换为人类可读关键字的图像处理工具。 我需要:

    初始化/声明 1000 个静态已知元素集 在动态元素和全部 1000 个元素之间执行 10 次比较(总共 10x1000 次比较) 重复第 1 步和第 2 步,上千张图像。

每个元素都是这样的结构:

struct KnownColor
    cv::Scalar rgb;
    std::string name;
    std::vector<std::string> strings;

    KnownColor ( cv::Scalar rgb, std::string name, std::vector<std::string> strings) :
        rgb(rgb),
        name(name),
        strings(strings) ;
;

目前我正在使用静态std::vector&lt;&gt; 来存储它们。为了初始化这个向量,我目前正在使用一个名为 once 的函数,并将我的 1000 个元素推入向量中。每个结构都使用 KnownColor 构造函数进行初始化:

static std::vector<CustomStruct> Vector;    

void vectorInit() //I call this only once per image:

    ...
    Vector.push_back(KnownColor(Scalar(188,198,204),"Metallic Silver",std::vector<std::string>"gray"));
    Vector.push_back(KnownColor(Scalar(152,175,199),"Blue Gray",std::vector<std::string>"gray","blue"));
    ... (1000 push_back in total)

比较函数,是返回最接近的“knownColor”及其人类可读关键字的标量之间的自定义欧几里德距离:

double min = std::numeric_limits<double>::max();
int index=0;
for(int i=0; i<KnownColors.size(); i++)

    double tmp = scalarLABDistance(rgb,KnownColors[i].rgb);
    if(tmp < distanceThreshold )
    
        min = tmp;
        break;
    
    if(tmp < min )
    
        min = tmp;
        index = i;
    

return KnownColors[index].strings;

目前很遗憾,该程序是从 php 调用的,并且需要为每个图像(客户端请求)执行一次。

我想知道静态初始化是否会更好(初始化更快?迭代更快?),或者是否有更好的方法来比较静态元素集合而不使用std::vector

【问题讨论】:

您的性能关注的是初始化时间还是比较时间?您已经展示了初始化。大概初始化只发生一次。 您可以通过在第一次 push_back 之前调用 Vector.reserve(1000) 来加快初始化代码的速度。 什么样的比较?您是在比较绝对相等(这样您可以在第一次 false 比较后短路)还是在做一些绝对需要每次都进行 1000 次比较的事情? 我们不知道你到底在做什么,所以没有办法知道最快的方法是什么。 @GuillermoMP:速度建议:看看您是否可以将其作为守护进程运行并通过本地 Unix 套接字进行通信。 【参考方案1】:

我在类似情况下所做的是编写一个程序来为我构建一个 C 文件,其中包含我需要已经整理好的数据结构。通常我用 Perl 或 Python 写这个。数据可能是生成的,也可能是从数据文件中读取的。

您可以在编译时构建一个 Boost 数组,这不需要时间进行初始化。但是,在任何桌面类型的 CPU 上,将 1000 个元素写入向量应该是超快的。

搜索你的 1000 个元素是一个更大的问题。

你说你在寻找欧几里得距离。游戏开发者用来解决这个问题的是一种称为二进制空间分区的技术。这可能会帮助你。它的工作方式非常粗略,是将 2D 空间划分为 4 个正方形。一个 3D 空间被分成 8 个立方体。然后将这些空间中的每一个进一步划分,直至最小的有用单元。这提供了一种快速搜索树的方法。但是,在搜索不适合一个分区的区域时会变得复杂。您可能决定搜索多棵树或在它接触的所有树中放置对象的副本。对于圆形或球体,您可能会退回到完美的距离计算,或者您可能只是将其细分为正方形/立方体,直到最小的单位并将其称为足够接近。有很多例子和文献。

而且,我几乎可以肯定你可以散列它,因为 2D BSP 中的一个点是一串 2 位位置值,它只是一个不同大小的整数,具体取决于你的 BSP 分辨率。

看起来另一个不错的选择可能是 kd-tree。那是一个“k”维树。我没有用过,但从我刚刚读到的关于它们的信息来看,它们看起来对这个很有用。

【讨论】:

-1 表示过早发布。等到问题被正确指定。 @KarolyHorvath:就在问题标题和他的第一段中。 不,不是。你有一堆不合理的假设,例如散列为评估比较提供了有意义的结果。 @KarolyHorvath:看起来他添加了一条评论说欧几里得距离,所以你是对的。我假设平等。我将更新答案以删除有关哈希表的内容,其余的可能仍然有用。 还有赞,我不是在搜索而是比较元素。我用详细信息扩展了这个问题。还是谢谢你。

以上是关于执行数千次比较的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

计算连接查询行数的最快方法

计算一个非常大的表中确切行数的最快方法?

Python:仅使用 1 个外生变量执行数百万次简单线性回归的最快方法

2D滚动窗口分位数的最快方法?

如何用最快的速度读出大小为10G的文件的行数?弄懂 python 的迭代器

压缩算法的比较