减法的字节数学速度更快,最小为0

时间:2016-05-12 03:19:33

标签: java

我正在为两个大型ByteBuffers的每第四个字节执行以下操作。 (从第一个中减去秒的alpha值; alpha不能低于0; RGBA数据。)

static void subtractAlphaSecondFromFirst (ByteBuffer first, ByteBuffer second, int pixelCount) {
    for (int i = 3; i < pixelCount * 4; i = i + 4) {
        byte a = first.get(i);
        byte b = second.get(i);
        first.put(i, (byte)Math.max(0, a - b));
    }
}

在我加入JNI之前,我想看看我是否可以在(byte)Math.max(0, a - b)表达式上获得一些速度提升。是否有一些可以完成相同操作的按位操作?我认为几乎可以肯定有一种更快的方法来做到这一点,而不是将两个字节提升为整数,对它们运行max(),然后再回到一个字节,但我很难想出一个。

后来如果我将它移植到C,我想我仍然会保持相同的等式。

3 个答案:

答案 0 :(得分:0)

也许您可以使用ternary operator

进行快速比较和减法
static void subtractAlphaSecondFromFirst (ByteBuffer first, ByteBuffer second, int pixelCount) {
    for (int i = 3; i < pixelCount * 4; i = i + 4) {
        byte a = first.get(i);
        first.put(i, (b > a ? 0 : a-b));
    }
}

在这种情况下&#34;(b> a?0:a-b)&#34;表示&#34;如果b大于a,则评估为0,否则评估为(a - b)&#34;

答案 1 :(得分:0)

您可以尝试使用饱和减法的无分支版本。这可能会减少内循环中分支错误预测的次数。像这样:

static void subtractAlphaSecondFromFirst(ByteBuffer first, ByteBuffer second, int pixelCount) {
    for (int i = 3; i < pixelCount * 4; i = i + 4) {
        int a = first.get(i) & 0xFF;
        int b = second.get(i) & 0xFF;
        int v = a - b;
        // Propagate sign bit into all bits and invert
        // Mask will be 0 if v is negative, -1 otherwise
        int mask = (v >> (Integer.SIZE - 1)) ^ -1;
        first.put(i, (byte)(v & mask));
    }
}

不幸的是,我没有真正的方法知道这是否会改善你的事情或让它们变得更糟。我还提供了一个解决方案,我认为这是一个签名/未签名的问题,如评论中所述。

答案 2 :(得分:0)

所以当我昨晚发布问题时,我觉得自己很昏昏欲睡,因为我在用例中忽略了一个关键事实:每个字节的值总是0或FF!

所以位操作版本很简单:

first.put(i, (byte)((a^b)&a));

我对它进行了基准测试,使用随机源数据时,它比我原来的版本快了大约25%。