我似乎无法在C#中创建一个高性能的D-ary Heap
类;硬编码的子女数量(BinaryHeap
,TernaryHeap
等)似乎表现得更好。
我的BinaryHeap
和D-ary Heap
与d=2
之间代码的唯一区别在于d
是先前的const
,而且readonly成员变量在后者(和readonly has no affect on performance)。
我猜测const
版本可能会编译为一个位移操作,而成员变量版本可能会编译为memory-fetch + devision。
有没有办法可以像我这样声明我的班级:
public class DaryHeap<T, const uint(d)> : IEnumerable<T> where T : IComparable<T>
其中 const uint(d)
会告诉编译器“d
是编译时uint
值”。因此,让D-ary Heap
与d=2
的{{1}}表现与BinaryHeap
相同。
答案 0 :(得分:1)
当我尝试使用D-ary堆(1,2)时,我发现了类似的东西(在这些主题中未提及),然后放弃了。没有太多与D相关的值。 4和8是关于所有的。 16,很少。 2,不是真的:在我的测试中,4-ary 总是更快(即使在“不应该”的情况下)。我还测试了2的非幂,也没有提到,因为它们很糟糕。
所以我决定制作一些硬编码版本。这违反了一些编码原则,但由于性能是我首先使用D-ary堆的主要原因,因此不使D成为常数的性能损失仅仅是不可接受的。
基本上只有D的两个值很重要,因此复制/粘贴代码的数量实际上并不高。
答案 1 :(得分:1)
CLR泛型比C ++模板更受限制。
但是还有其他类型的模板。以T4为例。您可以将D-ary堆编写为T4模板,然后从中生成具体版本。我假设您使用Visual Studio,它可以自动与T4集成。这样可以保持DRY(因为您只修改模板本身)并且速度很快(因为您有最佳实现)。最好的部分是你可以使用真正的语言来生成代码,而不是像使用C ++模板那样使用元语言。