我有一个使用OpenMP并行for循环的程序.在循环中,线程将写入共享变量,因此我需要同步它们。然而,有时我可以得到段错误或双自由或损坏错误。有人知道会发生什么吗?谢谢和问候!以下是代码:
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;
}
}
......
}更新:
与我上一篇文章double free or corruption一样,该代码在单线程上运行良好,但给出了多线程的运行时错误。错误时有发生。如果我运行两次,一个是分段故障,另一个是双倍免费或腐败。
发布于 2010-02-02 07:02:13
让我们来看看您的分段故障线:
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可能是完全不可线程的:
库分配少量的存储,这是程序生命周期内构建的所有搜索结构所共享的。因为数据是共享的,所以即使删除了所有单个结构,也不会将其解除分配。
如上所述,并行数据修改总是会出现问题,因为库本身有一些共享数据--因此它本身并不是线程安全的:/。
https://stackoverflow.com/questions/2182306
复制相似问题