你在所有方面都是对的。ILNumerics 目前没有可用的优化包。但是,如您所知,.NET 的一大优势是易于合并外部包。这里有几个选项:
PInvoke(本机模块)
由于大多数现有优化包都作为本机模块存在,因此 PInvoke 是您的朋友。有几种工具可用于自动生成 DLLImport 签名。就个人而言,我更喜欢手动创建这些签名。特别是,因为大多数科学包都公开了一个简单的签名,该签名很容易合并到 .NET 中。然而,从本机代码到托管代码的回调以及复杂结构的编组可能会出现问题。(所以,我们将帮助您解决所有问题......
.NET 模块
您可能会找到一个现有的 .NET 优化模块。请参阅这篇文章(C# 中的免费优化库)或尝试 Microsoft Solver Foundation。更好的模块可能已经存在——我已经有一段时间没有寻找了。除非非常仔细地完成实现,否则它们可能会或可能不会由于糟糕的(无)内存管理而影响性能。(据我所知,没有其他项目可以像 ILNumerics 那样有效地跟踪内存?)。但是,连接这些库会很容易:不需要 DLLImport 签名。但为了从 ILNumerics 内存管理中获益,您必须在“ILNumerics”端管理数组内存。因此,将一些 System.Array 提供给其他 .NET 函数的模式是:
.... inside ILNumerics function
using (ILScope.Enter(inparameter1,inparameter2)) {
....
ILArray<double> A = zeros(1000,1000); // allocate memory for external use
var aArray = A.GetArrayForWrite(); // fetch reference to underlying System.Array
callOtherLib(aArray); // let other lib use and fill the array
// proceed normally with A...
return A + 1 * 2 ... ;
}
如果另一个库仅从给定数组中读取,A.GetArrayForRead() 可能会提供更好的性能。通过使用该方案,可以确保最有效的内存使用 - 至少在您的实现的 ILNumerics 方面。
混合来自双方的数据结构不会造成任何伤害 - 但通常也不会带来太多优势:这通常会降低语法的便利性,因为没有用于混合矩阵实现的组合运算符。此外,您通常会被迫将矩阵访问分解为元素操作,这可能会导致性能较低的解决方案。因此,我建议采用模块化设计,API 清晰分离。
上面的内存方案也适用(并推荐)用于连接本机库。
仅使用 ILNumerics
另一种方法 - 当然 - 是使用 ILNumerics 内置函数和数组功能自行重新实现某些模块。这种方式是强制性的,以便将任何包合并到官方 ILNumerics 发行版中。它带来了几个优点:可以利用方便的 ILNumerics 语法,自动受益于高效的 ILNumerics 内存管理,并且代码最终将完全独立于平台。此外,这为您提供了关于算法所需功能的最大灵活性。