【问题标题】:Implementing C# language extensions实现 C# 语言扩展
【发布时间】:2011-12-28 18:08:49
【问题描述】:

使用Parallel Linq 等系统,可以将匿名函数、查询等的执行拆分到单个机器内的多个内核和线程上。我希望能够使用标准语言结构(如 for 循环(如 Parallel.For())、值类型(如 ints、structs 等)等)将其扩展为跨多台机器运行,并保留应用程序源修改到最低限度。理想情况下,这将允许我打开一个项目,向方法添加一个属性,然后重新编译以访问增强的功能。

看来我需要一些类似的东西:

  1. 能够捕获已编译的代码块(例如 lambda)并将其连同所需的任何数据一起传递给在另一个节点上运行的工作进程,或者

  2. 提供一个预处理器来捕获有问题的代码,在一种模板项目中编译它,该模板项目将替换变量引用等,引用一个可以处理网络通信、缓存和访问任何其他代码的类所需的资产,并将生成的 DLL 发送到在其他机器上运行的任何可用工作节点。

Roslyn 似乎提供了一些在这里有用的工具。有没有办法挂钩到当前的编译管道以允许这样做?

编辑

好的,我知道这是可能的,because these guys did it。问题是,如何

【问题讨论】:

  • 好的,关闭器 - 这到底是如何过于本地化的?
  • 因为你必须是这里唯一想要实现 C# 语言扩展来创建 OpenCL 内核的人。
  • 好吧,忘记 OpenCL 部分。您将如何进入编译阶段以自定义代码生成以跨异构平台分布执行?这对我来说似乎更清楚。我们从什么时候开始解决有关特定应用程序的问题?!​​
  • 我不认为这是本地化的。 OP 真正要求的只是编写 LINQ 查询提供程序以将 C# 转换为 OpenCL 的指导,这是一项艰巨的任务,但前期并不十分复杂。见here
  • @JohnSaunders 然后“没有办法做到这一点”是一个有效的回答,因为我在问是否可能,如果可以,如何。我不明白这如何使问题“过于本地化”。

标签: c# language-extension


【解决方案1】:

使用 Parallel Linq 等系统,可以在一台机器内跨多个内核和线程拆分匿名函数、查询等的执行。我希望能够使用标准语言结构(如 for 循环(如 Parallel.For())、值类型(如整数、结构等))将其扩展为在多台机器上运行,并将应用程序源修改保持在最低限度.

听起来不错。事实上,我们在微软研究院有一个非常相似的系统,但显然我无法讨论细节。

我需要能够捕获已编译的代码块(例如 lambda)并将其传递给在另一个节点上运行的工作进程以及所需的任何数据

好的,你明白了。我们将该功能添加到 C# 3。这就是 LINQ to SQL 的工作原理。 不知何故 LINQ 查询必须进入数据库。编译后的 lambda 在客户端机器上被查询,转换成一个查询发送到服务器节点,然后将结果发回。

Roslyn 似乎提供了一些在这里有用的工具。有没有办法挂钩到当前的编译管道以允许这样做?

这不是罗斯林的目的; Roslyn 并不是要向 C# 语言添加新功能。这是为了更容易分析代码以构建诸如重构引擎之类的东西。

您不需要挂钩到编译管道。 PLINQ 不改变编译器,LINQ to SQL 不改变编译器,等等。当您将 lambda 转换为表达式树时,编译器会发出在运行时创建表示 lambda 的表达式树的代码。您可以查询该表达式树,将其序列化到网络中的另一台机器,对其进行反序列化,将其转换为委托并运行它,如果这是您喜欢做的事情。

您可能需要编写自己的表达式树序列化器和反序列化器,但它们是非常简单的数据结构。作为不可变的树应该使它们很容易序列化和反序列化;它们不能真正形成复杂的网络,因为它们总是从叶节点向上构建。

【讨论】:

  • 谢谢,埃里克。我没有考虑到与 LINQ to SQL 的相似性。我今天早上开始玩表情树,并尽量不要大声笑。 :)
  • 跟进:这非常有效。感谢 MS 提供了如此灵活、可扩展的系统。提供代码即数据的编译时验证非常酷。
【解决方案2】:

您不必扩展语言分析来做 Brahma 所做的事情。他刚刚实现了一个自定义查询提供程序,它解析表达式树并发出 GPGPU 代码(LINQ to SQL 做同样的事情,但使用 SQL)。

我在 MSDN here 上链接了一个基本指南,可以帮助您启动并运行实现 IQueryable 提供程序。

困难的部分将是遍历表达式树并生成 OpenCL 代码。一旦你能做到这一点,你只需将它传递给 Cloo,你就应该开始运行了。

编辑

您使用属性[Kernel] 将编译标准 .NET 代码的工具链接到 GPU 代码。他们通过让构建后工具在编译后的 IL 中查找属性并执行 IL 重写以生成 GPU 调用来做到这一点。这类似于PostSharp,一种AOP 解决方案。

IL 重写既费时又费力,但你也可以走这条路。

【讨论】:

  • 太棒了;感谢您的回复。我仍然对在不必使用自定义提供程序的情况下实现这一点感到好奇 - 例如捕获循环等并将它们替换为对此类提供程序的引用 - 但这将解决问题。
  • +1。有一些库声称可以更轻松地实现自定义 LINQ 提供程序,例如 re-linq
  • 表达式树可以表示自 C# 4 起的循环和大多数语句构造。如果您不想要 LINQ 样式语法,只需自己解析表达式树。请记住,您可以将 lambda 函数直接分配给表达式对象,例如:Expression<Func<int,string>> someExpression = (i) => return "Hey!"
  • 我见过对表达式树的引用,但还没有研究过。这似乎很有希望。
  • 已编辑问题以安抚反对者;您的原始答案仍然适用。我会改回问题,但我可能会被闪电击中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-17
  • 1970-01-01
  • 2018-12-28
相关资源
最近更新 更多