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

pthread条件变量vs win32事件(linux vs windows ce),windows,linux,events,pthreads,windows-ce,Windows,Linux,Events,Pthreads,Windows Ce,我正在ARMIMX27板上进行Windows CE和Linux之间的性能评估。这段代码已经为CE编写,它测量了执行不同内核调用所需的时间,比如使用操作系统原语(如互斥和信号量)、打开和关闭文件以及联网 在将这个应用程序移植到Linux(pthreads)的过程中,我偶然发现了一个无法解释的问题。几乎所有的测试都显示性能从5倍提高到了10倍,但不是我的版本(和),CE实际上“赢”了这个测试 为了模拟行为,我使用了pthreads条件变量(我知道我的实现没有完全模拟CE版本,但它足以进行评估) 测试

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

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

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

测试代码使用两个线程,它们使用事件相互“乒乓”


Windows代码: 线程1:(我测量的线程)


Linux代码: 线程1:(我测量的线程)

我的
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 event_flag
{
    pthread_mutex_t mutex;
    pthread_cond_t  condition;
    unsigned int    flag;
};
问题:
  • 为什么我在这里看不到性能提升
  • 可以采取哪些措施来提高性能(例如,是否有更快的方法来实施CEs行为)
  • 我不习惯编写pthread,我的实现中是否存在可能导致性能损失的bug
  • 有其他的图书馆吗

请注意,调用
pthread\u cond\u signal()
时,您不需要持有互斥锁,因此您可以通过在发出条件信号之前释放互斥锁来提高条件变量“event”实现的性能:

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);
}

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

只有在您能够错过事件的情况下,这种类型的实现才有效。我只是测试了一下,遇到了很多死锁。这样做的主要原因是,条件变量只会唤醒已经在等待的线程。之前发出的信号丢失

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

我想不出比使用初始化为零的信号量更好的解决方案了(POSIX版本非常容易使用),使用
sem\u post()
表示
set()
sem\u wait()
表示
wait()
。使用
sem\u getvalue()


也就是说,我不知道POSIX信号量是否只是Linux信号量的一个简洁接口,或者性能损失是什么。

您可以检查这个实现。购买时不要期望性能有任何提高。LinuxSimple不支持本地事件之类的东西,仿真永远不会这么快。这与Windows中的条件变量的情况相同。旧的windows版本不支持它,模拟也相当复杂。@Zuljin:那里的实现与我的版本几乎相同:-(难道不能用其他原语实现吗?我所做或看到的所有测试都让CE轻松地赢得了同步对象,所以你的结果就是我所期望的。不过,你可能会发现Linux的netywork堆栈比CE的速度快得多(我上次测试它时肯定是这样的)。这就是为什么条件变量总是与…条件关联。您使用互斥来确保对该条件的一致访问,并在while循环中检查它。(以说明虚假唤醒,以及在通知后可能已更改条件的并发互斥获取线程。)我要讨论的问题是一个只发生一次的事件。请考虑一个分派其他线程的线程。例如,仅当分派的线程实际运行了一段时间后,您才希望继续执行分派器。为此,我使用了两个信号量:分派器创建线程并发布“分派”信号量。分派的线程就是这样。在设置分派信号量之后,分派器等待工作者发布工作者信号量。这种机制使用上述事件失败,因为在大多数情况下,工作者将错过分派器的信号并永远阻塞。当然是的。这就是为什么条件变量不关注事件,而是关注条件。您的条件是一个变量,例如一个bool,它标记“go for it!”,您的工作者将读取该变量。如果它为false,它将等待条件_变量,直到有信号出现,它将唤醒并检查“go for it”标记。如果该标记为true,则意味着该信号在工作者到达该点之前发送,因此它甚至不会等待。互斥锁在这里是一个使用正确的内存屏障访问此标志。它不应该首先是cond_信号,然后是mutex_解锁吗?按此顺序排列,会留下一个小的可能性,即其他参与者在执行cond_信号之前锁定mutex,这样,信号服务员就不会在收到信号后自动锁定mutex。
while (1)
{
    eventflag_wait(event1);
    eventflag_set(event2);
}
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 event_flag
{
    pthread_mutex_t mutex;
    pthread_cond_t  condition;
    unsigned int    flag;
};
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);
}