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