【发布时间】:2012-01-09 01:42:41
【问题描述】:
我已经用 C 语言(在 python 扩展中)实现了一个工作队列模式,但我对性能感到失望。
我有一个包含粒子列表(“元素”)的模拟,我对执行时间步所需的所有计算所花费的时间进行了基准测试,并将其与所涉及的粒子数量一起记录下来。我在四核超线程 i7 上运行代码,所以我期待性能上升(所需时间下降),线程数最多约为 8,但最快的实现没有工作线程(函数只是执行而不是添加到队列中,)并且对于每个工作线程,代码变得越来越慢(比每个新线程的非线程实现的时间要多一步!)我快速查看了我的处理器使用情况应用程序,而且无论有多少线程正在运行,python 似乎从未真正超过 130% 的 CPU 使用率。该机器有足够的余量,整体系统使用率约为 200%。
现在我的队列实现的一部分(如下所示)是从队列中随机选择一个项目,因为每个工作项目的执行都需要锁定两个元素,并且相似的元素将彼此靠近队列。因此,我希望线程选择随机索引并攻击队列的不同位以最小化互斥冲突。
现在,我了解到我最初使用 rand() 的尝试会很慢,因为我的随机数不是线程安全的(这句话有意义吗?不确定...)
我已经尝试使用 random() 和 drand48_r 实现(尽管不幸的是,后者似乎在 OS X 上不可用)但对统计数据无济于事。
也许其他人可以告诉我问题的原因可能是什么?代码(worker 函数)在下面,如果您认为 queue_add 函数或构造函数中的任何一个也可能有用,请大声喊叫。
void* worker_thread_function(void* untyped_queue) {
queue_t* queue = (queue_t*)untyped_queue;
int success = 0;
int rand_id;
long int temp;
work_item_t* work_to_do = NULL;
int work_items_completed = 0;
while (1) {
if (pthread_mutex_lock(queue->mutex)) {
// error case, try again:
continue;
}
while (!success) {
if (queue->queue->count == 0) {
pthread_mutex_unlock(queue->mutex);
break;
}
// choose a random item from the work queue, in order to avoid clashing element mutexes.
rand_id = random() % queue->queue->count;
if (!pthread_mutex_trylock(((work_item_t*)queue->queue->items[rand_id])->mutex)) {
// obtain mutex locks on both elements for the work item.
work_to_do = (work_item_t*)queue->queue->items[rand_id];
if (!pthread_mutex_trylock(((element_t*)work_to_do->element_1)->mutex)){
if (!pthread_mutex_trylock(((element_t*)work_to_do->element_2)->mutex)) {
success = 1;
} else {
// only locked element_1 and work item:
pthread_mutex_unlock(((element_t*)work_to_do->element_1)->mutex);
pthread_mutex_unlock(work_to_do->mutex);
work_to_do = NULL;
}
} else {
// couldn't lock element_1, didn't even try 2:
pthread_mutex_unlock(work_to_do->mutex);
work_to_do = NULL;
}
}
}
if (work_to_do == NULL) {
if (queue->queue->count == 0 && queue->exit_flag) {
break;
} else {
continue;
}
}
queue_remove_work_item(queue, rand_id, NULL, 1);
pthread_mutex_unlock(work_to_do->mutex);
pthread_mutex_unlock(queue->mutex);
// At this point, we have mutex locks for the two elements in question, and a
// work item no longer visible to any other threads. we have also unlocked the main
// shared queue, and are free to perform the work on the elements.
execute_function(
work_to_do->interaction_function,
(element_t*)work_to_do->element_1,
(element_t*)work_to_do->element_2,
(simulation_parameters_t*)work_to_do->params
);
// now finished, we should unlock both the elements:
pthread_mutex_unlock(((element_t*)work_to_do->element_1)->mutex);
pthread_mutex_unlock(((element_t*)work_to_do->element_2)->mutex);
// and release the work_item RAM:
work_item_destroy((void*)work_to_do);
work_to_do = NULL;
work_items_completed++;
success = 0;
}
return NULL;
}
【问题讨论】:
标签: python c multithreading random