为了最大限度地提高关键方法的性能,in another question it was suggested我分配并使用本机内存而不是修复它。
我在C#工作,没有使用不安全代码和使用P / invoke的经验。我没有在Google上找到任何相关示例,MSDN article about VirtualAlloc也没有帮助。
这是一种被称为十亿次的方法,并且每一点性能都是可取的。
public static readonly int[] HR = new int[32487834];
public unsafe int eval(int c1, int c2, int c3, int c4, int c5, int c6, int c7)
{
fixed (int* HR = Evaluator.HR)
{
int p = HR[53 + c1];
p = HR[p + c2];
p = HR[p + c3];
p = HR[p + c4];
p = HR[p + c5];
p = HR[p + c6];
return (HR[p + c7]);
}
}
如果您感兴趣,它是TwoPlusTwo-Evaluator的C#端口,它使用123mb查找表返回随机7张牌扑克的等级进行比较。在我的机器上,我以随机顺序平均大约80M评估/ s,并且连续顺序(c1 = 0,c2 = 1,循环递增每个变量,最多52个)的500M评估/秒。
答案 0 :(得分:1)
您的示例的主要问题是您必须使用fixed
指令 来自外部 循环代码。在这个嵌套函数中使用它不会真正有用,并且可能会使事情变得更糟,因为它会使C#在内部调用其GC内存固定API。所以一个更好的解决方案就是这样的代码:
public unsafe int eval(int* HR, int c1, int c2, int c3, int c4, int c5, int c6, int c7)
{
int p = HR[53 + c1];
p = HR[p + c2];
p = HR[p + c3];
p = HR[p + c4];
p = HR[p + c5];
p = HR[p + c6];
return (HR[p + c7]);
}
fixed
本质上是GCHandle.AddrOfPinnedObject的语言构造同义词。在你的情况下,省略了对8个数组提取的边界检查,每次进入该功能时,都会通过GC固定和取消固定内存的成本...但可能不是很多。
使用P / Invoke通常并不简单,除非你想花几天时间熟悉这个领域,否则我会建议不要这样做。如果您还不熟悉通过C ++进行的Win32 / WinAPI编程,则更具挑战性。最好重新编写代码,以便尽可能将内存固定在链上。出于这个特定目的,您甚至可以为该数组创建一个GCHandle作为对象构造函数的一部分。
答案 1 :(得分:0)
尝试使用C ++ / Cli:
ref class Evaluator
{
public:
static Int32* HR;
static Evaluator()
{
int size = 32487834;
HR = (INT*)malloc(size * 4);
}
static Int32 Eval(Int32 c1, Int32 c2, Int32 c3, Int32 c4, Int32 c5, Int32 c6, Int32 c7)
{
Int32 p = HR[53 + c1];
p = HR[p + c2];
p = HR[p + c3];
p = HR[p + c4];
p = HR[p + c5];
p = HR[p + c6];
return (HR[p + c7]);
}
};