滥用OpenMP?
我有一个使用OpenMP来并行化for-loop的程序。在循环内部,线程将写入共享变量,所以我需要同步它们。但是,我有时可能会遇到段错误或双重释放或损坏错误。有人知道会发生什么?感谢致敬!下面是代码:滥用OpenMP?
void KNNClassifier::classify_various_k(int dim, double *feature, int label, int *ks, double * errors, int nb_ks, int k_max) {
ANNpoint queryPt = 0;
ANNidxArray nnIdx = 0;
ANNdistArray dists = 0;
queryPt = feature;
nnIdx = new ANNidx[k_max];
dists = new ANNdist[k_max];
if(strcmp(_search_neighbors, "brutal") == 0) {// search
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps);
}else if(strcmp(_search_neighbors, "kdtree") == 0) {
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps); // double free or corruption
}
for (int j = 0; j < nb_ks; j++)
{
scalar_t result = 0.0;
for (int i = 0; i < ks[j]; i++) {
result+=_labels[ nnIdx[i] ]; // Segmentation fault
}
if (result*label<0)
{
#pragma omp critical
{
errors[j]++;
}
}
}
delete [] nnIdx;
delete [] dists;
}
void KNNClassifier::tune_complexity(int nb_examples, int dim, double **features, int *labels, int fold, char *method, int nb_examples_test, double **features_test, int *labels_test) {
int nb_try = (_k_max - _k_min)/scalar_t(_k_step);
scalar_t *error_validation = new scalar_t [nb_try];
int *ks = new int [nb_try];
for(int i=0; i < nb_try; i ++){
ks[i] = _k_min + _k_step * i;
}
if (strcmp(method, "ct")==0)
{
train(nb_examples, dim, features, labels);// train once for all nb of nbs in ks
for(int i=0; i < nb_try; i ++){
if (ks[i] > nb_examples){nb_try=i; break;}
error_validation[i] = 0;
}
int i = 0;
#pragma omp parallel shared(nb_examples_test, error_validation,features_test, labels_test, nb_try, ks) private(i)
{
#pragma omp for schedule(dynamic) nowait
for (i=0; i < nb_examples_test; i++)
{
classify_various_k(dim, features_test[i], labels_test[i], ks, error_validation, nb_try, ks[nb_try - 1]); // where error occurs
}
}
for (i=0; i < nb_try; i++)
{
error_validation[i]/=nb_examples_test;
}
}
......
}
UPDATE:
正如我过去后double free or corruption,代码运行正常用单线程,但给出了多线程运行时错误。该错误随时发生变化。如果我运行两次,其中一次将会出现段错误,另一次将会出现双倍的空闲或腐败现象。
让我们来看看你的分割断层线:
result+=_labels[ nnIdx[i] ];
result
是本地的 - 确定。
nnIdx
是本地 - 也行。
i
是本地 - 仍然可以。
_labels
...这是什么?
它是全球性的吗?你有没有通过#pragma shared
定义访问权限?
也是一样的前者:
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps);
似乎我们这里有一个问题,是不是容易解决 - _search_struct不是线程安全的 - 大概值它是由线程同时修改。你必须有一个专用的_search_struct每线程,可能是通过在classify_various_k中分配它。
的真正的坏消息却是,ANN可能是完全无螺:
库分配少量的存储量 ,这是通过在 程序的内置所有 搜索struc-功能共享一生。因为共享数据 ,所以在删除所有单个结构 时,不会释放它,甚至不会释放 。
如上所述,并行数据修改总会有问题,因为库本身有一些共享数据 - 因此它本身不是线程安全的:/。
_labels是类KNNClassifier的数据成员。它并没有明确宣布为共享敌人openmp。此外,如果我运行我的progrom两次,一个将seg段,ang其他将是双重免费或腐败,如在我上一篇文章。即错误不是固定的。 – Tim 2010-02-02 07:08:23
_search_struct-> annkSearch(queryPt,k_max,nnIdx,dists,_eps)用于在* _search_struct的k-d树中组织的某些点中查找查询点*特征的k_max最近邻点。 k-n邻居的索引存储在nnIdx中,并且它们与查询点的距离为dists。 – Tim 2010-02-02 07:18:19
@Tim,更新了答案。 – 2010-02-02 08:29:45
在段错误之前,i和nnIdx [i]的值是什么? – 2010-02-02 07:09:36
我是6. nnIdx [i]是1708204069,这是非常错误的,超出了可以被认为合理的方式。不知道为什么。将值分配给nnIdx的元素的函数属于ANN,库为 近似最近邻搜索,请参阅http://www.cs.umd.edu/~mount/ANN/ – Tim 2010-02-02 07:32:40