- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
F# 引用是一个很棒的功能,它允许我们将 F# 表达式视为正常的 F# 值。在我的上下文中,我使用 F# 引用对 Gpu 内核进行编码,并将其编译为 Gpu bitcode 模块。
有一个问题。我不想每次都编译 Gpu 内核,我想缓存编译后的 Gpu bitcode 模块。因此我需要一个键,或者来自 F# 引用值的标识。我想要一个缓存系统,例如:
let compile : Expr -> GpuModule
let cache = ConcurrentDictionary<Key, GpuModule>()
let jitCompile (expr:Expr) =
let key = getQuotationKey(expr)
cache.GetOrAdd(key, fun key -> compile expr)
open Microsoft.FSharp.Quotations
let foo (expr:Expr) =
printfn "%O" expr
[<EntryPoint>]
let main argv =
for i = 1 to 10 do
foo <@ fun x y -> x + y @>
0
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: br IL_00a2
// loop start (head: IL_00a2)
IL_0008: ldtoken '<StartupCode$ConsoleApplication2>.$Program'
IL_000d: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0012: ldc.i4.5
IL_0013: newarr [mscorlib]System.Type
IL_0018: dup
IL_0019: ldc.i4.0
IL_001a: ldtoken [mscorlib]System.Int32
IL_001f: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0024: stelem.any [mscorlib]System.Type
IL_0029: dup
IL_002a: ldc.i4.1
IL_002b: ldtoken [FSharp.Core]Microsoft.FSharp.Core.Operators
IL_0030: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0035: stelem.any [mscorlib]System.Type
IL_003a: dup
IL_003b: ldc.i4.2
IL_003c: ldtoken [mscorlib]System.Tuple`2
IL_0041: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0046: stelem.any [mscorlib]System.Type
IL_004b: dup
IL_004c: ldc.i4.3
IL_004d: ldtoken [mscorlib]System.String
IL_0052: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0057: stelem.any [mscorlib]System.Type
IL_005c: dup
IL_005d: ldc.i4.4
IL_005e: ldtoken [mscorlib]System.Tuple`5
IL_0063: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0068: stelem.any [mscorlib]System.Type
IL_006d: ldc.i4.0
IL_006e: newarr [mscorlib]System.Type
IL_0073: ldc.i4.0
IL_0074: newarr [FSharp.Core]Microsoft.FSharp.Quotations.FSharpExpr
IL_0079: ldc.i4 372
IL_007e: newarr [mscorlib]System.Byte
IL_0083: dup
IL_0084: ldtoken field valuetype '<PrivateImplementationDetails$ConsoleApplication2>'/T1805_372Bytes@ Program::field1806@
IL_0089: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
IL_008e: call class [FSharp.Core]Microsoft.FSharp.Quotations.FSharpExpr [FSharp.Core]Microsoft.FSharp.Quotations.FSharpExpr::Deserialize40(class [mscorlib]System.Type, class [mscorlib]System.Type[], class [mscorlib]System.Type[], class [FSharp.Core]Microsoft.FSharp.Quotations.FSharpExpr[], uint8[])
IL_0093: call class [FSharp.Core]Microsoft.FSharp.Quotations.FSharpExpr`1<!!0> [FSharp.Core]Microsoft.FSharp.Quotations.FSharpExpr::Cast<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, int32>>>(class [FSharp.Core]Microsoft.FSharp.Quotations.FSharpExpr)
IL_0098: call void Program::foo(class [FSharp.Core]Microsoft.FSharp.Quotations.FSharpExpr)
IL_009d: nop
IL_009e: ldloc.0
IL_009f: ldc.i4.1
IL_00a0: add
IL_00a1: stloc.0
IL_00a2: ldloc.0
IL_00a3: ldc.i4.s 11
IL_00a5: blt IL_0008
// end loop
IL_00aa: ldc.i4.0
IL_00ab: ret
FSharp.Quotations.FSharpExpr::Deserialize40
重新创建报价对象; <@ ... @>
,他们将创建一个新的 Expr
例如,即使静态字段相同。所以我不能使用 Expr
实例作为键,最好获取静态字段 token 并将其用作键。但我不知道如何获取这些信息; Var
在引号中进行比较(当 var 具有对应物并且具有相同的类型时)。按照他的回答,我进行了以下测试并且它有效:
let comparer =
let rec compareQuots vs = function
| ShapeLambda(v,e), ShapeLambda(v',e') ->
compareQuots (vs |> Map.add v v') (e,e')
| ShapeCombination(o,es), ShapeCombination(o',es') ->
o = o' && (es.Length = es'.Length) && List.forall2 (fun q1 q2 -> compareQuots vs (q1, q2)) es es'
| ShapeVar v, ShapeVar v' when Map.tryFind v vs = Some v' && v.Type = v'.Type ->
true
| _ -> false
let rec hashQuot n vs = function
| ShapeLambda(v,e) ->
hashQuot (n+1) (vs |> Map.add v n) e
| ShapeCombination(o,es) ->
es |> List.fold (fun h e -> 31 * h + hashQuot n vs e) (o.GetHashCode())
| ExprShape.ShapeVar v ->
Map.find v vs
{ new System.Collections.Generic.IEqualityComparer<_> with
member __.Equals(q1,q2) = compareQuots Map.empty (q1,q2)
member __.GetHashCode q = hashQuot 0 Map.empty q }
type Module = int
let mutable counter = 0
let compile (expr:Expr) =
counter <- counter + 1
printfn "Compiling #.%d module..." counter
counter
let cache = ConcurrentDictionary<Expr, Module>(comparer)
let jitCompile (expr:Expr) =
cache.GetOrAdd(expr, compile)
[<Test>]
let testJITCompile() =
Assert.AreEqual(1, jitCompile <@ fun x y -> x + y @>)
Assert.AreEqual(1, jitCompile <@ fun x y -> x + y @>)
Assert.AreEqual(1, jitCompile <@ fun a b -> a + b @>)
Assert.AreEqual(2, jitCompile <@ fun a b -> a + b + 1 @>)
let combineExpr (expr:Expr<int -> int -> int>) =
<@ fun (a:int) (b:int) -> ((%expr) a b) + 1 @>
// although (combineExpr <@ (+) @>) = <@ fun a b -> a + b + 1 @>
// but they are treated as different expr.
Assert.AreEqual(3, jitCompile (combineExpr <@ (+) @>))
Assert.AreEqual(3, jitCompile (combineExpr <@ (+) @>))
Assert.AreEqual(4, jitCompile (combineExpr <@ (-) @>))
最佳答案
每次通过循环创建一个新对象并不一定意味着该对象不能用作键,只要对象每次比较相等即可。
您将遇到的真正问题是,“相同”的引用对您来说意味着与 F# 编译器不同的东西,尤其是在引用中的变量方面。例如,您可以验证
<@ [1 + 1] @> = <@ [1 + 1] @>
true
, 和
<@ fun x -> x @> = <@ fun y -> y @>
false
(希望这是有道理的,因为 lambda 相当于重命名,但不完全相同)。也许更令人惊讶的是,你会看到
<@ fun x -> x @> = <@ fun x -> x @>
false
.这是因为每个引号中的变量被视为不同的变量,它们恰好共享相同的名称。您将在循环中看到相同的行为 - 每次迭代的变量
x
被认为是不同的。
IEqualityComparer<Quotations.Expr>
.我认为这样的事情应该可以识别任何相同的模变量重命名的引用:
let comparer =
let rec compareQuots vs = function
| Quotations.ExprShape.ShapeLambda(v,e), Quotations.ExprShape.ShapeLambda(v',e') ->
compareQuots (vs |> Map.add v v') (e,e')
| Quotations.ExprShape.ShapeCombination(o,es), Quotations.ExprShape.ShapeCombination(o',es') ->
o = o' && (es.Length = es'.Length) && List.forall2 (fun q1 q2 -> compareQuots vs (q1, q2)) es es'
| Quotations.ExprShape.ShapeVar v, Quotations.ExprShape.ShapeVar v' when Map.tryFind v vs = Some v' && v.Type = v'.Type ->
true
| _ -> false
let rec hashQuot n vs = function
| Quotations.ExprShape.ShapeLambda(v,e) ->
hashQuot (n+1) (vs |> Map.add v n) e
| Quotations.ExprShape.ShapeCombination(o,es) ->
es |> List.fold (fun h e -> 31 * h + hashQuot n vs e) (o.GetHashCode())
| Quotations.ExprShape.ShapeVar v ->
Map.find v vs
{ new System.Collections.Generic.IEqualityComparer<_> with
member __.Equals(q1,q2) = compareQuots Map.empty (q1,q2)
member __.GetHashCode q = hashQuot 0 Map.empty q }
let cache = ConcurrentDictionary<Expr, Module>(comparer)
关于f# - 我可以获得 F# 引用的标识吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34611616/
我正在 R 中使用 RecordLinkage 库。 我有一个包含 ID、姓名、电话、邮件的数据框 我的代码如下所示: ids = data$id pairs = compare.dedup(data
我目前正在构建一个新的 ASP.NET MVC 5 项目,我想在 9 月左右发布。我需要选择一个成员(member)系统,但我目前对我应该采取哪个方向感到很困惑。当前的 SimpleMembershi
我正在为 Brackets 定制一个大纲插件,它使用正则表达式来识别当前打开的文件的大纲。 我使用 regex101.com 创建了以下正则表达式(使用环视来确定该行以七个空格开头并以“SECTION
我已在表中将一列标记为“身份” create table Identitytest( number int identity(1,001) not null, value varch
我不知道那是字符串还是数组... char str4[100] = { 0 }; 那个代码是字符串? 如果是,它打印什么? 最佳答案 I dont know if that a string or a
我这里有一个场景,当用户想要重置密码时,系统必须通过电子邮件向用户发送一个随机生成的临时密码。我尝试将临时密码存储到数据库中的一个新列中,但我不确定这种方法是否有效。有些人建议使用 token,如下所
Vista 的现代 Windows 应用程序中有一个很好的功能。它是窗口标题中的图片。例如新的 skype (v4) 和 google chrome 都有它。 我在想它背后的技术是什么?如果你关闭 a
比较相同泛型类型的两个实例的最佳(最简洁和最佳)方法是什么,以便比较引用类型的身份(相同的对象,所以不是调用 Equals) 和 value 类型以获得值 equality。 目前我这样做: stat
我使用以下 C# 代码来获取处理器信息。如果我在虚拟机上运行我的应用程序,则管理类为空。我使用 Oracle VM VirtualBox 作为我的虚拟电脑 (Windows XP SP3) Syste
创建帐户后,Windows 帐户(本地、域、Active Directory)的 SID 是否会更改?如果是,在什么条件下。 最佳答案 是的,当您将帐户迁移到新域时,它会发生变化。 这就是您 AD 帐
我正在使用 Identity Server 4 并且我已经自定义了我的 ASP.NET Identity 用户,如下所示: public class ApplicationUser : Identit
我创建了一个 IIS 管理工具,旨在创建新应用程序、将它们分配到新的 AppPool,并为与该 AppPool 关联的身份添加所需的文件夹 ACL。根据this article ,每当创建新的应用程序
我使用 ASP.NET Identity .. 我想将 session 超时设置为无限制或最大值。我试过一些东西,但没有效果。注意:我使用共享主机。 谢谢你。 //web.config /
我有一台 Win 2008 R2 Enterprise 机器,它在几个网站上运行良好,每个网站都有自己的应用程序池。 我在向 IIS AppPool\A、IIS AppPool\B 等授予权限(使用
现有数据库模型(简化): 1 个用户可以加入 1 个或多个访问组。 1个AccessGroup可以有1个或多个AccessItens。 MSDN Says: When an identity is c
在具有单个表继承层次结构的 Hibernate/JPA 环境中使用 PostgreSQL 时,我看到了奇怪的行为。 首先是我的环境: PostgreSQL 8.3 Spring 2.5.6SEC01
是声明“一个类具有唯一标识”。是真是假? Java 中的对象有其唯一标识(至少通过它们的内存地址),但是类也有唯一标识吗?由于类不是对象,我对此感到困惑。或者是否需要实例化一个类(甚至可能)? 最佳答
我正在尝试通过将主要组件分解为单独的网络服务器来使用微服务架构来实现网络应用程序。我正在使用 ASP.NET Identity(仅电子邮件/用户名登录,无 Facebook 等)和“主”应用程序服务器
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: How do you like your primary keys? 我知道使用 GUID 的好处,以及使用
我可以这样获取所有用户 var users = UserManager.Users.ToList(); 我能找到这样的角色 var role = db.Roles.SingleOrDefault(m
我是一名优秀的程序员,十分优秀!