【发布时间】:2015-10-05 07:55:23
【问题描述】:
是否可以生成代表的身份以将其与其他代表区分开来?想想这段代码:
Func<int, int, int> delegate1 = a, b => a + b;
Func<int, int, int> delegate2 = a, b => a + b;
Func<int, int, int> delegate3 = a, b => a - b;
let id1 = id(delegate1);
let id2 = id(delegate2);
let id3 = id(delegate3);
Assert(id1 == id2);
Assert(id1 != id3);
我要解决的问题是,我想在 .NET 中缓存一些 JIT 编译的 GPU 代码。为了方便使用,我想让用户发送委托,如果委托相同,我们尝试从缓存中找出GPU代码,而不是每次都JIT编译:
Parallel(outputA, inputA1, inputA2, a, b => a + b); //should JIT compile GPU code, and cache it by its identity
Parallel(outputB, inputB1, inputB2, a, b => a + b); //should NOT JIT compile GPU code, and use the cached GPU code by its identity
一种可能的解决方案是比较表达式字符串,但是捕捉到clouser仍然有问题,例如:
int c = 0;
Expression<Func<int, int, int>> delegate1 = (a, b) => a + b + c;
c += 1;
Expression<Func<int, int, int>> delegate2 = (a, b) => a + b + c;
Expression<Func<int, int, int>> delegate3 = (a, b) => a - b - c;
Console.WriteLine(delegate1);
Console.WriteLine(delegate2);
Console.WriteLine(delegate1.ToString() == delegate2.ToString());
Console.ReadKey();
感谢@SWeko 和@Luaan 指出,在上面的示例中,delegate1 和delegate2 实际上是相同的。但是缓存委托的目的是在以下用法中:
int c = 1;
Parallel(outputA, inputA1, inputA2, (a,b) => a+b); //do JIT compile of GPU code
c += 1;
Parallel(outputB, inputB1, inputB2, (a,b) => a+b); //as the delegate is same then the previouse one, it will not do JIT GPU code compiling, but then, that is wrong!
【问题讨论】:
-
也许您可以使用Expression trees 而不是
Func。我不确定他们是否按照要求实现了Equals和GetHashCode,但是您可以遍历该结构并且可以创建自己的HashCode——但这并不像听起来那么简单。 - 我不确定这是否会带来性能优势。 -
@Verarind 然后我们可以从委托创建表达式树,但问题又来了,我们可以简单地比较两个表达式树对象的相等性吗?
-
您的代表不相同。检查
delegate1.Method。检查delegate2.Method。它们是两个不同的功能,碰巧做同样的事情。您询问代表的身份,但您的代码已经正确检测到这一点。你真正感兴趣的是别的东西。 -
@XiangZhang 正如我之前所说:不确定。也许
Equals被实现来处理具有相同内容的不同实例,但我想不是。在这种情况下,您必须自己实现它。 -
实际上,在第二个示例中,两个代表都将使用更新后的值
c。