pthread条件变量vs win32事件(linux vs windows-ce)

时间:2012-01-16 17:03:13

标签: windows linux events pthreads windows-ce

我正在使用arm imx27板在Windows CE和Linux之间进行性能评估。代码已经为CE编写并测量了执行不同内核调用所需的时间,例如使用互操作和信号量等操作系统原语,打开和关闭文件以及联网。

在我将此应用程序移植到Linux(pthreads)期间,我偶然发现了一个我无法解释的问题。几乎所有测试都显示性能提高了5到10倍,但不是我的win32 events版本SetEventWaitForSingleObject),CE实际上“赢了”了这个测试。

要模仿我使用pthreads条件变量的行为(我知道我的实现并没有完全模拟CE版本,但它足以进行评估)

测试代码使用两个使用事件互相“ping-pong”的线程。


Windows代码:

主题1:(我测量的主题)

HANDLE hEvt1, hEvt2;
hEvt1 = CreateEvent(NULL, FALSE, FALSE, TEXT("MyLocEvt1"));
hEvt2 = CreateEvent(NULL, FALSE, FALSE, TEXT("MyLocEvt2"));

ResetEvent(hEvt1);
ResetEvent(hEvt2);

for (i = 0; i < 10000; i++)
{
    SetEvent (hEvt1);
    WaitForSingleObject(hEvt2, INFINITE);
}        

主题2:(只是“回复”)

while (1)
{
    WaitForSingleObject(hEvt1, INFINITE);
    SetEvent(hEvt2);
}

Linux代码:

主题1:(我测量的主题)

struct event_flag *event1, *event2;
event1 = eventflag_create();
event2 = eventflag_create();

for (i = 0; i < 10000; i++)
{
    eventflag_set(event1);
    eventflag_wait(event2);
}

主题2:(只是“回复”)

while (1)
{
    eventflag_wait(event1);
    eventflag_set(event2);
}

我对eventflag_*的实施:

struct event_flag* eventflag_create()
{
    struct event_flag* ev;
    ev = (struct event_flag*) malloc(sizeof(struct event_flag));

    pthread_mutex_init(&ev->mutex, NULL);
    pthread_cond_init(&ev->condition, NULL);
    ev->flag = 0;

    return ev;
}

void eventflag_wait(struct event_flag* ev)
{
    pthread_mutex_lock(&ev->mutex);

    while (!ev->flag)
        pthread_cond_wait(&ev->condition, &ev->mutex);

    ev->flag = 0;

    pthread_mutex_unlock(&ev->mutex);
}

void eventflag_set(struct event_flag* ev)
{
    pthread_mutex_lock(&ev->mutex);

    ev->flag = 1;
    pthread_cond_signal(&ev->condition);

    pthread_mutex_unlock(&ev->mutex);
}

struct

struct event_flag
{
    pthread_mutex_t mutex;
    pthread_cond_t  condition;
    unsigned int    flag;
};

问题:

  • 为什么我不在这里看到性能提升?
  • 可以做些什么来提高性能(例如,有更快的方法来实现CE行为)?
  • 我不习惯编写pthreads,我的实现中是否有错误导致性能下降?
  • 是否有替代库?

2 个答案:

答案 0 :(得分:3)

请注意,在调用pthread_cond_signal()时不需要持有互斥锁,因此您可以通过在发出条件信号之前释放互斥锁来提高条件变量'event'实现的性能:< / p>

void eventflag_set(struct event_flag* ev)
{
    pthread_mutex_lock(&ev->mutex);

    ev->flag = 1;

    pthread_mutex_unlock(&ev->mutex);

    pthread_cond_signal(&ev->condition);
}

这可能会阻止唤醒的线程立即阻塞互斥锁。

答案 1 :(得分:0)

这种类型的实施仅在您能够错过活动时才有效。我刚测试它并遇到了很多死锁。这样做的主要原因是条件变量只唤醒已经在等待的线程。之前发出的信号丢失了。

如果条件已经发出信号,则没有计数器与允许等待线程简单地继续的条件相关联。 Windows事件支持此类用法。

我认为没有比使用信号量(POSIX版本非常易于使用)更好的解决方案,初始化为零,使用sem_post() set()sem_wait() { {1}}。您肯定可以想到一种方法,使用wait()

将信号量计数到最大值1

那说我不知道​​POSIX信号量是否只是Linux信号量的简洁接口或性能损失是什么。