Java - Python 共享内存通信

4
我们有一个Java程序和一个Python程序,需要以乒乓方式使它们配合工作,每次交换长度为100,000的整数数组,并且完成工作需要花费大约0.1-1秒钟:
  1. Java 执行一些操作并将长度为100,000的int数组发送到...
  2. Python 执行一些操作并向其发送一个新的长度为100,000的数组...
  3. Java 执行一些操作...等等

请注意:

  • 每个程序都需要等待另一个程序完成其操作。
  • 它们将在同一台Linux机器上运行。
  • 我们将进行蒙特卡罗模拟,因此速度很重要。

我更熟悉Java,并且了解基于共享内存的文件方法可能是最快的。这篇文章似乎适用于Java方面,但我应该如何让每个程序等待/阻塞对方完成其工作并在其开始读取之前更新共享内存?我听说过一个叫做“信号量”的东西,但弄不明白。

这些是我的备选方案,但也许它们更好?


4
或许这个建议有点蠢,但如果它们在同一台机器上运行,那么你不能通过Jython来执行Python程序吗?这样做应该会简化通信。 - UnholySheep
3
我希望您能看到在Java和Python之间切换所带来的复杂性。我建议使用Jython或者放弃其中一种语言,全部采用Java或Python进行计算。 - GhostCat
1
是的,进程间通信相对简单,但如果需要使用多种语言,则会变得更加复杂。 - Jacob G.
1
如果你正在进行蒙特卡罗模拟,瓶颈应该是你使用的 CPU 数量。使用回环应该足够快。你可以在几毫秒内通过回环传输 400KB 的数据。 - Peter Lawrey
1
在Windows笔记本电脑上,我可以使用普通套接字在回环中以每秒300 MB的速率在两个JVM之间发送数据(以400 KB块为单位)。这意味着每个400 KB的往返平均需要1.3毫秒。建议检查数据的缓冲效率。 - Peter Lawrey
显示剩余9条评论
2个回答

1
使用快速的中间数据服务器来协助它们之间的通信。Redis 可以胜任这项工作。您需要两个数据结构:
1. 列表(包含 100,000 个项目)。我们将其称为 my_project:list。 2. 锁。这可以是 Redis 字符串,设置为 "Python" 或 "Java"。
然后进行以下交互:
1. Python 和 Java 都轮询 Redis 锁。如果它等于 "Python",那么轮到 Python。如果是 "Java",那么轮到 Java。 2. 轮到哪个程序时,该程序进入工作模式并执行其需要做的操作 my_project:list,然后将锁设置为另一个程序的轮次。 3. 无限重复此过程。

有道理,但担心轮询策略会比在套接字上阻塞要慢得多。 - Pengin
2
你可以运行一个timeit来测试。只要所有东西都在同一台机器上,轮询不会导致超过几毫秒的延迟。如果你的时间范围是100ms-1s,这不会对你的计时产生太大影响,但会极大地简化你的开发。你将无法很好地调试套接字阻塞。你正在交换约0.1-5%的速度下降,以获得更大的简单性和开发速度。这是一个很好的交易。利用节省下来的额外时间加速你的Java和Python程序,它们将占据你绝大部分的处理时间。 - Eli

1
你可以尝试使用jep将Java和Python结合在同一个进程中。最新版本增加了使用numpy ndarrays和Java direct buffers之间的内存共享支持。这样可以在不复制数据的情况下共享数据,从而获得最佳性能。

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