我正在为两个大型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,我想我仍然会保持相同的等式。
答案 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%。