【问题标题】:Efficient comparison of small integer vectors小整数向量的有效比较
【发布时间】:2015-08-30 15:11:55
【问题描述】:

我有小向量。它们中的每一个都由 0 到 15 之间的 10 个整数组成。这意味着向量中的每个元素都可以用 4 位写入。因此,我可以连接我的向量元素并将整个向量存储在单个 long 类型中(在 C、C++、java 中......)

如果对于 0,...,9, v1[i] >= v2[i] 中的每个 i,向量 v1 支配向量 v2

我想编写一个方法compare(long v1, long v2),如果没有一个向量占主导地位,则返回 0,如果第一个占主导地位,则返回 1,如果第二个占主导地位,则返回 -1。

除了获取每个 i 分量并进行 10 倍的普通整数比较之外,还有什么有效的方法来实现比较?

编辑

如果 v1 与 v2 完全相同,返回 1 或 -1 都可以

【问题讨论】:

  • 如果您可以假设 x86-only 那么 SSE 可能是要走的路 - 将您的向量存储为 16 x 8 位整数,然后实现比较非常简单。
  • 您确定您的问题定义正确吗? compare(v, v) 应该返回什么?我假设您为此需要 0,即如果至少一个元素更大,v1 仅在 v2 中占主导地位?

标签: c integer compare bit-manipulation string-comparison


【解决方案1】:

使用位操作可以做到这一点。将您的值隔开,使每个值占用 5 位,其中 4 位用于值,在最重要的位置有一个空 0 作为一种间距位。

在每个值之间放置一个间距位会阻止借用/进位在相邻值之间传播,这意味着您可以通过使用常规整数加法或减法对向量执行某些类似 SIMD 的算术运算。我们可以用减法来做向量比较。

要进行测试,您可以将其中一个向量中的所有间距位设置为 1,然后减去第二个。如果间距位下面的 4 位中的值在第二个中更大,那么它将携带间距位中的位并将其设置为零,如果不是,则它将保持为 1(第一个值更大大于或等于第二个)。如果第一个向量支配第二个向量,那么减法后所有的间距位都将是一个。

使用整数的简单演示:

#define SPACING_BITS ((1<<4)|(1<<9)|(1<<14)|(1<<19))
int createVector(int v0, int v1, int v2, int v3)
{
    return v0 | (v1 << 5) | (v2 << 10) | (v3 << 15);
}

int vectorDominates(int vectorA, int vectorB)
{
     // returns 1 if vectorA dominates vectorB:
     return (((vectorA | SPACING_BITS) - vectorB) & SPACING_BITS) == SPACING_BITS;
}

int compare(int vectorA, int vectorB)
{
    if(vectorDominates(vectorA, vectorB))
        return 1;
    else if(vectorDominates(vectorB, vectorA))
        return -1;
    return 0;
}

您可以将其扩展为使用 64 位值,使用 50 位来存储 10 个值。您还可以在比较函数中内联对vectorDominates 的调用。

Demo

【讨论】:

  • 在你控制函数中,你不需要在比较之前与空格位进行AND吗? return ((vectorA | SPACING_BITS) - vectorB) &amp; SPACING_BITS == SPACING_BITS; 之类的东西?如果我理解你的(非常聪明的)逻辑,你只是想看看间距位是否不受减法的影响。
  • @TripeHound 是的,这绝对正确。我之前检查为零,但随后翻转比较以处理“或等于”并忘记掩盖结果。谢谢!
  • 进一步思考,如果您存储了(((vectorA | SPACING_BITS) - vectorB) &amp; SPACING_BITS),那么如果vectorA 占主导地位(如您所见),这不是SPACING_BITS,或者如果vectorB 占主导地位则全为零(即所有“元素" 的 B 造成了“借用”?因此您只需要调用一次比较函数吗?
  • vectorB 仍然可以支配vectorA 而不会引起借位(因此仍然有一些借位),因为元素只需要等于或大于,不一定大于。所以不幸的是,测试全零是行不通的。
  • 实际上,这个问题似乎不明确,因为“dominates”被定义为一个向量的所有元素都大于or_equal-to 另一个:如果所有元素都相等,那么根据这个定义,两者都占主导地位!
【解决方案2】:

嗯,在 C 语言中,您可能会利用矢量化来做到这一点。我认为直接比较 4 位操作数是不可能的,所以在做之前你将不得不重新打包(动态地或者只是将你的数据以更合适的格式保存)到 8 位比较。由于 10 * 8 = 80 大于 64,因此您将需要 128 位向量指令。

不确定 Java VM 是否支持,但this question suggests that JNI is the answer,即从 Java 调用 C 代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 2018-11-17
    • 2012-10-04
    • 2011-05-10
    • 2012-10-15
    相关资源
    最近更新 更多