c - IPC瓶颈?

标签 c windows winapi ipc shared-memory

我有两个进程,一个生产者和一个消费者。 IPC 是通过 Win32 上的 OpenFileMapping/MapViewOfFile 完成的。

生产者从另一个源接收视频,然后将其传递给消费者,并通过两个事件完成同步。

对于制作人:

Receive frame
Copy to shared memory using CopyMemory
Trigger DataProduced event
Wait for DataConsumed event

对于消费者

Indefinitely wait for DataProducedEvent
Copy frame to own memory and send for processing
Signal DataConsumed event

如果没有这些,视频的平均帧率为 5 fps。 如果我在两侧添加事件,但没有 CopyMemory,它仍然在 5fps 左右,尽管慢了一点。 当我添加 CopyMemory 操作时,它下降到 2.5-2.8fps。 Memcpy 甚至更慢。

我很难相信简单的内存复制会导致这种速度减慢。 有什么补救措施吗?

这是我创建共享内存的代码:

HANDLE fileMap = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, fileMapSize, L"foomap");
void* mapView = MapViewOfFile(fileMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, fileMapSize);

尺寸为1024 * 1024 * 3

编辑 - 添加实际代码:

关于制作人:

void OnFrameReceived(...)
{
    // get buffer
    BYTE *buffer = 0;
...

    // copy data to shared memory
    CopyMemory(((BYTE*)mapView) + 1, buffer, length);

    // signal data event
SetEvent(dataProducedEvent);

    // wait for it to be signaled back!
    WaitForSingleObject(dataConsumedEvent, INFINITE);
}

对于消费者:

while(WAIT_OBJECT_0 == WaitForSingleObject(dataProducedEvent, INFINITE))
    {   
        SetEvent(dataConsumedEvent);
    }
<小时/>

好吧,看来从 DirectShow 缓冲区复制到共享内存毕竟是瓶颈。我尝试使用命名管道来传输数据,猜猜结果如何 - 性能得到了恢复。

有谁知道这可能是什么原因吗?

添加一个我之前认为不相关的细节:生产者被注入(inject)并挂接到 DirectShow 图上以检索帧。

最佳答案

内存复制涉及某些幕后操作,对于视频来说这可能很重要。

我会尝试另一条路线:为每个帧或多个帧创建一个共享 block 。依次命名它们,即 block1、block2、block3 等,以便接收者知道接下来要读取哪个 block 。现在直接将帧接收到分配的 block X,通知消费者新 block 的可用性,并立即分配并开始使用另一个 block 。消费者映射该 block 并且不复制它 - 该 block 现在属于消费者并且消费者可以在进一步处理中使用原始缓冲区。一旦消费者关闭了该 block 的映射,该映射就会被销毁。所以你会得到一个 block 流并避免阻塞。

如果帧处理不需要太多时间而创建共享 block 却需要太多时间,您可以创建一个足够大的共享 block 池,以确保生产者和消费者永远不会尝试使用相同的 block (您可以使用以下方法使方案复杂化)一个信号量或互斥体来保护每个 block )。

希望我的想法很清楚 - 通过使用生产者中的 block 而不是消费者中的 block 来避免复制

关于c - IPC瓶颈?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3556953/

相关文章:

php - 单行 if 语句或没有大括号的 if 语句是不好的做法吗?

c - C中较大的整数到较小的无符号类型转换

c - 位图字体渲染问题

windows - Go test编译成功,但是go build没有

c++ - 将 vector 字符串的值传递给 C++ 中的 win32 函数 SetWindowText

c - 解释这个汇编代码

regex - 取消 KeyUP 事件的处理程序?网络

c - 使用C程序从pendrive中删除所有文件

windows - 在Windows资源管理器中获取选定的文件或文件夹

c# - 默认堆栈大小在 .NET 3.5 和 4.x 之间变化?