C#中的虚拟内存地址管理

3
我正在开发一个蒙特卡罗定价器,需要提高引擎的效率。
蒙特卡罗路径由第三方库(使用c++)创建。
定价是在IronPython中完成的(由最终用户创建的脚本)。
其他所有内容都由C#应用程序驱动。
定价过程如下:
C#应用程序请求路径并收集它们。
C#应用程序将路径推送到脚本中,脚本对其进行定价并返回值。
C#应用程序向最终用户显示结果。
收集路径的数量和大小事先已知。
我有两种解决方案,各有优点和缺点:
请求路径生成,对于每条路径,要求脚本返回结果,最后在处理完所有路径后聚合结果。
请求路径生成,收集所有路径,一次请求脚本处理所有路径,并返回最终价格。
第一种解决方案在所有情况下都很好,但随着请求的路径数量增加,性能会降低(我认为这是由于多次调用IronPython引起的)。
第二种解决方案更快,但如果请求的路径数太大,则可能会出现“内存不足”异常(我认为这不是足够的虚拟内存寻址空间)。
我选择了折中的方法,并处理一堆路径,然后聚合价格。现在我想通过事先知道可以处理多少路径而进一步提高性能,而不会触发“内存不足”异常。
我做了数学计算,并预先知道给定请求的路径大小(在内存中)。但是,由于我相当确定这不是内存问题,而更多地是虚拟内存寻址问题。
所以所有这些文本由以下两个问题总结:
1.是否有可能事先知道我的进程需要多少虚拟内存地址来存储n个类实例(已知内存大小和结构)?
2.是否有可能知道我的进程还有多少虚拟内存地址可用?
顺便说一句,我正在32位计算机上工作。
感谢您的帮助。

生产者/消费者...线程? - Guillaume
有什么理由不直接购买一台64位计算机并安装超过4GB RAM的内存呢?这样做可以解决问题,同时也能提高可扩展性。 - TomTom
@Tomtom:做不到,我无法控制目标环境。它可能是64位或32位。 - Guillaume
然后你也可以在它上面设置LAA标志。这样可以让你获得3GB而不是2GB。 - TomTom
@TomTom:尝试不错,但是坦率地说,如果去找IT基础设施负责人要求更改他提供给用户的标准构建,我想他会嘲笑我的。 - Guillaume
那么现在是时候寻找另一份工作了。真的。我们在一个项目中也有过同样的争论,现在我们将服务器迁移到了64位,并为我们的项目获得了一个“未批准”的数据库。32位标准构建用于大数据操作,“我宁愿为一家没有停留在1900年的公司工作”。 - TomTom
2个回答

1

1

在.NET中查找对象占用多少内存是一项相当困难的任务。我遇到过同样的问题好几次。有一些不完美的方法,但没有一个非常精确。

我的建议是先估计一下路径需要多少内存,然后传递一堆路径,留出足够的安全余量。即使你每次只处理10个路径,你已经将开销降低了10倍。

你甚至可以将余量设置为可配置的,然后调整它,直到达到良好的平衡。更加优雅的解决方案是在另一个进程中运行整个过程,如果出现OutOfMemoryException异常,则使用较少的项目重新启动计算(并相应地调整余量)。然而,如果你有太多的数据导致内存不足,那么将其通过两个进程传递可能会有点慢(这也会复制数据)。

内存溢出是否是由于路径处理器中的某些缺陷引起的?可能是内存泄漏吗?这些都可能存在于C++和.NET中。


对于另一个进程,解决方案不是一个选项,我说的是100,000个路径。使用另一个进程来找到平衡太慢了。 - Guillaume
找到正确的平衡点是我所做的,通过推断路径数量。但问题在于路径对象的复杂性取决于用户请求(事先不知道),但在运行时知道。 - Guillaume
到底哪一部分是慢的?调用脚本的开销吗?还是脚本实际上能够并行处理多个路径?如果只是调用开销,也许您可以修改脚本容器,使其逐个处理路径,从而基本上减少了多次调用的开销,转化为您问题中的第一个选项? - Vilx-
开销是由C#调用脚本(C#调用IronPython)引起的,脚本按顺序处理路径,但问题在于我需要调用它的次数。如果我将路径分组为10个以处理100000个路径,则我将调用脚本10000次;如果我将路径分组为100000个,则我将调用“脚本”(IronPython)一次,从而将开销减少了10000倍。但没关系,你可以帮我找到一个解决方案。 - Guillaume
我在极端条件下进行了测试,这些条件并不现实。使用真实值时,开销并不那么重要。我将为标准路径找到最佳分组值,并根据用户请求的路径进行动态调整。 - Guillaume
好的,如果脚本按顺序处理它们,那么其中一定存在某个内存泄漏(或在.NET情况下是引用),否则它不会耗尽内存。也许可以调查这个方向? - Vilx-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接