Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对于C#28时间限制是否有解决办法?_C#_.net_Optimization_.net 4.0 - Fatal编程技术网

对于C#28时间限制是否有解决办法?

对于C#28时间限制是否有解决办法?,c#,.net,optimization,.net-4.0,C#,.net,Optimization,.net 4.0,我正在使用RedGate的性能分析器优化一个物理模拟程序。代码中处理碰撞检测的一部分有以下52个小检查,分别在两种情况下处理26个方向的三维单元 CollisionPrimitiveList cell = innerGrid[cellIndex + 1]; if (cell.Count > 0) contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts); cell = innerGrid[cel

我正在使用RedGate的性能分析器优化一个物理模拟程序。代码中处理碰撞检测的一部分有以下52个小检查,分别在两种情况下处理26个方向的三维单元

CollisionPrimitiveList cell = innerGrid[cellIndex + 1];
if (cell.Count > 0)
    contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);

cell = innerGrid[cellIndex + grid.XExtent];
if (cell.Count > 0)
    contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);

cell = innerGrid[cellIndex + grid.XzLayerSize];
if (cell.Count > 0)
    contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);
作为一个非常紧密的程序循环,所有这些都必须采用相同的方法,但我发现,突然,在我将区域从二维扩展到三维(计数从16增加到52个检查)之后,突然cell.count不再是内联的,尽管它是一个简单的getter。
public int Count{get{return Count;}}
这造成了巨大的性能损失,我花了相当长的时间才发现,当cell.Count出现在方法中28次或更少时,它每次都是内联的,但一旦cell.Count出现在方法中29次或更多,它就一次也没有内联(尽管绝大多数调用来自代码中很少执行的最坏情况部分。)

那么回到我的问题上来,有没有人有办法绕过这个限制?我认为简单的解决办法就是将计数字段设置为内部,而不是私有,但我希望有一个比这个更好的解决方案,或者至少是更好地了解情况。我希望微软在撰写High-p时会提到这种事情Performance Managed Applications(性能管理应用程序)页面位于,但遗憾的是它不是(可能是因为28个计数限制是多么任意?)

我正在使用.NET4.0

编辑:看起来我误解了我的小测试。我发现内联失败并不是因为方法本身被调用了28次以上,而是因为它们应该内联到的方法在某种标准下“太长”。这仍然让我困惑,因为我不明白一个简单的getter怎么可以合理地不内联(正如我的分析器清楚地告诉我的那样,使用内联的方法时性能会显著提高),但显然CLI JIT编译器拒绝内联任何内容,因为该方法已经很大了(通过使用细微的变化,我发现这个限制是代码大小(来自idasm)在1500的情况下,没有进行内联,即使在我的getter的情况下,一些测试表明这不会增加内联的额外代码开销)


谢谢。

我还没有测试过这一点,但一个可能的解决办法似乎是让多个属性返回相同的内容。可以想象,每个属性可以得到28条内联线


请注意,方法内联的次数很可能取决于该方法的本机代码的大小(请参阅),数字28是特定于该属性的。一个简单的属性可能比一个更复杂的方法内联更多次。

直接来说,这并不能解释为什么28是一个神奇的数字,但我很好奇,如果将所有候选CollisionListPrimitive实例整理成一个数组,然后调用数组循环中的“if count>0”块

是否再次内联调用cell.Count

e、 g


我知道性能是个问题,构建数组和循环数组时会有开销,但是如果cell.Count再次内联,整体性能是否还会更好/足够好?

我猜(虽然不是正面的)这可能与前面提到的问题有关——CLR可能正在为每个if语句分配一个新变量,并且这些变量的总数超过了64个。你认为可能是这样吗?

如果你真的关心性能,你就不会使用getter setter。它们只是碍手碍脚。有趣。听起来像是寄存器优化-也许分解IL会给出一些提示?Ron,我想这正好满足我的需要,但我也喜欢getter通过不允许写访问而提供的保护(Count实际上是链接列表中的节点数,如果意外更改,情况可能会非常糟糕).Jeremy,我可能会尝试查看IL,但我的印象是,它不会有帮助,因为内联只能由CLR JIT编译器完成。(我只能通过我的探查器了解内联)。阅读让我想到,此方法正在达到O(n^2)对O(n)的优化算法选择。来自网站:如果您找到解决方案的时间有限,一个好的方法可能是为较小的Ns执行最佳解决方案,并为较大的Ns返回到非最佳但快速的解算器。"我建议尝试将该方法分为两个子方法,然后依次调用它们-这可能会使您受到JIT的限制。@Alk:将属性getter设置为公共,将下划线成员设置为内部。这样您就不允许外部用户将其搞砸。虽然我不能说您已经找到了答案,但我尝试了您的多个属性的想法,这些属性可以urn发现了同样的事情,并惊讶地发现它实际上并没有导致内联,这使我意识到是父方法的大小,我粗略估计的调用数量,才是真正的罪魁祸首。鉴于我刚刚发现它是父方法代码的大小,这无疑会减少它足以导致内联再次发生。OTOH,这只对方法的一部分有效,因为许多单元格在测试之前必须进行范围检查。我试图通过添加任意的if语句来测试这一假设,这些if语句可能会导致这些假定的额外变量分配,但通过我的测试,这几乎没有dif引用,更确切地说,内联是否发生与代码大小有关。我确信真正不同的是本机大小,但ildasm报告的大小的阈值始终在1500或1501左右。@Akh:您的语句没有完全优化,对吗?它们有副作用吗?(试试condit)
CollisionPrimitiveList[] cells = new CollisionPrimitiveList {
    innerGrid[cellIndex + 1],
    innerGrid[cellIndex + grid.XExtent],
    innerGrid[cellIndex + grid.XzLayerSize]
    // and all the rest
};

// Loop over cells - for demo only. Use for loop or LINQ'ify if faster
foreach (CollisionPrimitiveList cell in cells) 
{
    if (cell.Count > 0)
        contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);  
}