1

我有一个客户端/服务器模型,每个客户端都可以向服务器发送一个任务——这称为任务请求。

这是我追求的简单分布式计算库的基础。

换句话说,如果一些普通的应用程序处理一个独立元素的数组,那么在数据并行模型中,每个处理器被分配处理数组的一部分。为了支持数据并行计算,核心库应该将任务划分为部分,将任务数据传输到特定 CPU 的本地内存,在该 CPU 上运行任务,将结果传输回调用者,并提供向调用者请求一些全局数据的能力。

数据并行图

  • 任务二进制(std::vector uint8_t) 和有效负载(std::vector uint8_t)。
  • 二进制文件只是一个已编译的任务/应用程序。
  • 有效负载是序列化为 uint8_t 的可选数据。

很简单:

class CGridTask
{

    public:
        ...

        bool        Run             ();    

    private:
        std::vector<uint8_t>        m_vBinary;
        std::vector<uint8_t>        m_vPayload;
        uint32_t                    m_uiUniqueId;

        ...
}

伪图显示了它是如何“工作”的:

[CLIENT1]---[SEND TASK with PAYLOAD: integer value = 10]-->[SERVER]

[SERVER]-->[RUN TASK with PAYLOAD]

[TASK, start]

[TASK, calculate...]
[TASK, calculate...]
[TASK, calculate...]
[TASK, integer value = 10 + some new value]

[TASK, return]

[SERVER]-->[SEND TASK to CLIENT1]

好的,所以当服务器调用时:

pGridTask->Run();

这是应该发生的事情:

bool CGridTask::Run()
{
    // Dump the binary to a temporary file
    Dump(m_vBinary);

    // Chmod +x
    system("chmod +x " + strTempopraryBinaryName);

    // Run the binary and pass m_vPayload
    ...how can i do this?...

    // Return true if binary executed
    return true;
}

这里唯一的问题是与执行的二进制文件共享 m_vPayload ......我该怎么做?

非常感谢您对此的任何意见!

4

4 回答 4

3

假设您要修改内存以便“主”进程可以看到它,您将需要设置共享内存或内存映射文件的区域。当新进程写入时,作为进程一部分分配的任何内存都将被复制,因此它不会被“共享”。

于 2013-05-04T15:19:07.577 回答
1

除了其他答案,您还可以考虑使用MPI消息传递接口标准,它有多种实现,包括Open MPI

当然 MPI 不是共享内存模型,但它似乎与您的“发送数据部分”的高级软件架构很接近。

MPI 是如此普遍,以至于一些高端的铁供应商(即百万欧元的超级计算机)提供了他们自己的硬件辅助 MPI 实现。

您还可以使用 Posix 共享内存,即shm_open(3)和朋友。参见shm_overview(7)。然后你可能想与 Posix 信号量同步。请参阅第一个sem_overview(7)

而且mmap(2)也可以用来共享内存(带MAP_SHARED标志)。

共享内存是不够的。您需要一些同步工具(告诉共享数据“准备好使用”......)。

也许你可以考虑 Pthreads。阅读一个好的Pthread 教程(最近的C++2011标准也提供了线程)。

并阅读Advanced Linux Programming以了解 Linux 下的许多 IPC 可能性。正如Siyam 所建议的,通常的pipe, fork, dup2, exec(和poll(2)用于输入和输出多路复用)值得考虑。

于 2013-05-04T16:11:51.217 回答
1

我不会推荐它.. 但这样你就可以“分享一切”

不要将fork()我们clone()与以下标志一起使用:CLONE_VM

CLONE_VM(自 Linux 2.0 起)

如果设置了CLONE_VM,则调用进程和子进程运行在同一个内存空间。特别是,调用进程或子进程执行的内存写入在其他进程中也是可见的。此外,子进程或调用进程使用 mmap(2) 或 munmap(2) 执行的任何内存映射或取消映射也会影响其他进程。

如果未设置 CLONE_VM,则子进程在执行 clone() 时在调用进程的内存空间的单独副本中运行。由其中一个进程执行的内存写入或文件映射/取消映射不会影响另一个,与 fork(2) 一样。

更多信息请访问http://linux.die.net/man/2/clone

但我相信你会遇到这个问题..动态分配的内存会泄漏..等等。

真正的解决方案是为有效载荷设置一个 mmap..

于 2013-05-04T15:28:28.903 回答
1

作为其他解决方案的替代方案,并且根据您的子进程的结构,您还可以通过管道(通常的pipe/fork/dup2/exec模式)与您的子进程进行通信。

当然性能比共享内存差,但整个架构更灵活,你的各种程序的耦合度会低得多:从孩子的角度来看,它从孩子的角度获取数据stdin并输出结果stdout,使其易于重用在其他上下文中(并且它还可以很容易地在任务服务器的上下文中重用“普通”交互式程序,而无需先调整它们)。

于 2013-05-04T15:33:29.873 回答