【发布时间】:2012-05-02 02:52:26
【问题描述】:
为了好玩而开发一个与规则无关的扑克模拟器。测试枚举中的瓶颈,以及总是从“唯一”数组中拉出的手,我发现了一个有趣的瓶颈。我测量了运行每个变体低于 1,000,000,000 次的平均计算时间,然后取其中最好的 100 次重复来让 JIT 和 Hotspot 发挥它们的魔力。我发现在计算时间(6ns vs 27ns)之间存在差异
public int getRank7(int ... cards) {
int q = (cards[0] >> 16) | (cards[1] >> 16) | (cards[2] >> 16) | (cards[3] >> 16) | (cards[4] >> 16) | (cards[5] >> 16) | (cards[6] >> 16);
int product = ((cards[0] & 0xFF) * (cards[1] & 0xFF) * (cards[2] & 0xFF) * (cards[3] & 0xFF) * (cards[4] & 0xFF) * (cards[5] & 0xFF) * (cards[6] & 0xFF));
if(flushes[q] > 0) return flushes[q];
if(unique[q] > 0) return unique[q];
int x = Arrays.binarySearch(products, product);
return rankings[x];
}
和
public int getRank(int ... cards) {
int q = 0;
long product = 1;
for(int c : cards) {
q |= (c >> 16);
product *= (c & 0xFF);
}
if(flushes[q] > 0) return flushes[q];
if(unique[q] > 0) return unique[q];
int x = Arrays.binarySearch(products, product);
return rankings[x];
}
问题肯定是 for 循环,而不是在函数顶部添加处理乘法。我对此有点困惑,因为我在每个场景中运行相同数量的操作......我意识到我在这个函数中总是有 6 张或更多卡,所以我通过将其更改为
public int getRank(int c0, int c1, int c2, int c3, int c4, int c5, int ... cards)
但是随着卡片数量的增加,我也会遇到同样的瓶颈。有什么办法可以绕过这个事实,如果没有,有人可以向我解释为什么相同数量的操作的 for 循环要慢得多吗?
【问题讨论】:
-
实际上,您在每个场景中运行的操作数量并不相同。在第一个示例中,如果
flushes[q] > 0或unique[q] > 0则跳过乘法。在第二个例子中,你总是做乘法。你确定这不会影响时间吗? -
阳性。我已经在完全删除乘法的情况下对其进行了测试,这在运行时没有变化。在检查之后将它移动到唯一只会为每对/两对/set/boat/quad类型的手增加一个额外的for循环的开销。作为一个概念证明,它通常是循环逻辑的一些隐藏方面,而不是循环本身定义的操作之一,我将其中使用的每个变量(x &card.length)移动到没有变化的方法参数,并且还尝试从cards.length切换到静态变量,没有任何变化。
标签: java performance algorithm time-complexity