代码之家  ›  专栏  ›  技术社区  ›  JulianR

否定布尔运算的真实性导致5x减速?

  •  1
  • JulianR  · 技术社区  · 14 年前

    this here ,我翻译了 pluecker_cls_cff

    public bool Intersect_2(ref RayPluecker r)
    {
      switch (r.Classification)
      {
    
        // 7 same-ish cases snipped
    
        case Classification.PPP:
    
          return !((r.Position.X > this.Max.X) || (r.Position.Y > this.Max.Y) || (r.Position.Z > this.Max.Z) ||
            (r.PlueckerCoefficient.X + r.Direction.X * this.Max.Y - r.Direction.Y * this.Min.X < 0) ||
            (r.PlueckerCoefficient.X + r.Direction.X * this.Min.Y - r.Direction.Y * this.Max.X > 0) ||
            (r.PlueckerCoefficient.Y + r.Direction.X * this.Min.Z - r.Direction.Z * this.Max.X > 0) ||
            (r.PlueckerCoefficient.Y + r.Direction.X * this.Max.Z - r.Direction.Z * this.Min.X < 0) ||
            (r.PlueckerCoefficient.Z - r.Direction.Z * this.Min.Y + r.Direction.Y * this.Max.Z < 0) ||
            (r.PlueckerCoefficient.Z - r.Direction.Z * this.Max.Y + r.Direction.Y * this.Min.Z > 0));
      }
    
      return false;
    }
    

    这似乎工作得很好,但对我来说似乎相当慢(250毫秒完成1000万个交集),所以我尝试了一些不同种类的微基准测试。在一个例子中,我去掉了 return 语句并反转所有比较( > <

    现在是:

    case Classification.PPP:
    
          return ((r.Position.X < this.Max.X) || (r.Position.Y < this.Max.Y) || (r.Position.Z < this.Max.Z) ||
            (r.PlueckerCoefficient.X + r.Direction.X * this.Max.Y - r.Direction.Y * this.Min.X > 0) ||
            (r.PlueckerCoefficient.X + r.Direction.X * this.Min.Y - r.Direction.Y * this.Max.X < 0) ||
            (r.PlueckerCoefficient.Y + r.Direction.X * this.Min.Z - r.Direction.Z * this.Max.X < 0) ||
            (r.PlueckerCoefficient.Y + r.Direction.X * this.Max.Z - r.Direction.Z * this.Min.X > 0) ||
            (r.PlueckerCoefficient.Z - r.Direction.Z * this.Min.Y + r.Direction.Y * this.Max.Z > 0) ||
            (r.PlueckerCoefficient.Z - r.Direction.Z * this.Max.Y + r.Direction.Y * this.Min.Z < 0));
    

    这个结果应该是一样的,对吧?看起来是这样的,因为它返回的结果与带有几个测试用例的否定版本相同。但是,在基准测试中,速度快了5倍(50毫秒完成1000万次交叉)!我确信它没有被优化,我的基准看起来是这样的:

    for (int i = 0; i < 10000000; i++)
    {
      if (!box.Intersect_3(ref ray))
      {
        throw new Exception();
      }
    }
    

    什么能解释这种巨大的差异?我正在x86上运行.NET4.0。

    2 回复  |  直到 5 年前
        1
  •  5
  •   AlcubierreDrive    14 年前

    你的第二个代码和你的第一个代码做的不一样。

    De Morgan's Laws

    我敢打赌,在你修复之后,你的两个版本将以相同的速度运行。

        2
  •  0
  •   Alex Morris    14 年前