Ошибка сегментации с MPI_Gather

Я использую MPI_Gather в первый раз и следую некоторым примерам, но по какой-то причине я получаю ошибку seg всякий раз, когда я ее вызываю. Соответствующий код находится здесь:

    //Get the top N matches for each node
    for (int j = 0; j < send_counts[id]; j++)
    {   
        data = read_file(my_dir + files[rec_buf[j]]);
        temp_results = circularSubvectorMatch(test_vectors[i], data, N); 
        results.insert(results.end(), temp_results.begin(), temp_results.end());
    }   

    std::sort(results.begin(), results.end(), sort_function);
    results.resize(N);

    //Send the N dissimilarities from each node to the root process and let it figure out
    //the Nth best one overall
    float *best_times = new float[N];
    for (int j = 0; j < N; j++)
    {   
        best_times[j] = results[j].dissimilarity;
    }   

    MPI_Barrier(MPI_COMM_WORLD);

    float *all_dissimilarities = NULL;
    if (id == 0)
    {   
       float *all_dissimilarities = new float[N * procs];
    }   

    MPI_Gather(best_times, N, MPI_FLOAT, all_dissimilarities, N, MPI_FLOAT, 0, MPI_COMM_WORLD);
    float *nth_best;
    if (id == 0)
    {
        std::sort(all_dissimilarities, all_dissimilarities + N * procs - 1);
        *nth_best = all_dissimilarities[N-1];
        *nth_best = 1.0;
    }
    MPI_Bcast(nth_best, 1, MPI_FLOAT, 0, MPI_COMM_WORLD);

    cout << "My id is " << id << "and I received: " << *nth_best << endl;

    //each process prints each result it has that is better than or equal
    //to the Nth best result calculated by the root process


    //output search vector and search time

    free(all_dissimilarities);
    free(best_times);
    MPI_Barrier(MPI_COMM_WORLD);

Я выделил буфер отправки и буфер приема, как в примере, может ли кто-нибудь пролить свет на то, почему я могу получить эту ошибку?


person Dan    schedule 19.04.2014    source источник
comment
Мне любопытно, почему вы используете std::vector в некоторых местах кода, но не используете его для таких очевидных вещей, как это: float *best_times = new float[N]; Затем вы усугубляете проблему, вызывая free() в памяти, выделенной с помощью new[]. В нынешнем виде ваш фрагмент кода вводит неопределенное поведение.   -  person PaulMcKenzie    schedule 20.04.2014
comment
Ну, на самом деле это мой первый класс C++, поэтому я немного новичок в этом языке. Это не причина ошибок seg, верно?   -  person Dan    schedule 20.04.2014
comment
Ваш код вводит неопределенное поведение. С таким кодом может случиться все что угодно. Мой совет: перестаньте читать книги по языку "C" или материалы, связанные с "C", и начните читать книги и материалы по C++. Кроме того, поскольку это фрагмент, мы не знаем, каковы значения j, осуществляется ли доступ к этому массиву файлов за пределами границ и т. д.   -  person PaulMcKenzie    schedule 20.04.2014
comment
Я подозреваю, что эта версия дает сбой, потому что ваш корневой процесс дважды объявил all_dissimilarities; второй раз, когда выделяется память (float *all_dissimilarities = new float[N * procs];), находится в блоке if и не влияет на all_dissimilarities, определенный в теле основной функции, который остается NULL. Теперь, почему векторная версия ниже дает сбой, я не уверен...   -  person T.C.    schedule 20.04.2014


Ответы (1)


В вашем коде есть две проблемы, одна из которых должна быть исправлена, а другая очистит ваш код. Кроме того, поскольку мы действительно не знаем, каковы значения «j», все, что я могу сделать, это предположить, что эти значения действительны.

Проблемы заключаются в следующем:

Проблема 1: вызов free() для данных, выделенных с помощью new[].

Никогда не смешивайте функции распределения и освобождения таким образом. Если вы выделяете с помощью new[], вы освобождаете с помощью delete[], а не free() и не delete (удаление без массива).

Проблема 2: Использование new[], когда в этом нет необходимости.

Вы можете заменить все эти вызовы new[] на std::vector. Вот переписывание вашего фрагмента кода с использованием вектора:

 //Get the top N matches for each node
#include <vector>
//...
typedef std::vector<float> FloatArray;
//...
for (int j = 0; j < send_counts[id]; j++)
{   
    data = read_file(my_dir + files[rec_buf[j]]);
    temp_results = circularSubvectorMatch(test_vectors[i], data, N); 
    results.insert(results.end(), temp_results.begin(), temp_results.end());
}   

std::sort(results.begin(), results.end(), sort_function);
results.resize(N);

//Send the N dissimilarities from each node to the root process and let it figure out
//the Nth best one overall
FloatArray best_times(N);
for (int j = 0; j < N; j++)
    best_times[j] = results[j].dissimilarity;

MPI_Barrier(MPI_COMM_WORLD);

float *pFirst = NULL;
FloatArray all_dissimilarities;
if (id == 0)
{
   all_dissimilarities.resize(N * procs);
   pFirst = &all_disimilarities[0];
}

MPI_Gather(&best_times[0], N, MPI_FLOAT, pFirst, N, MPI_FLOAT, 0, MPI_COMM_WORLD);
float nth_best;
if (id == 0)
{
    std::sort(all_dissimilarities.begin(), all_dissimilarities.end());
    nth_best = all_dissimilarities.back();
    nth_best = 1.0;
}
MPI_Bcast(&nth_best, 1, MPI_FLOAT, 0, MPI_COMM_WORLD);
cout << "My id is " << id << "and I received: " << nth_best << endl;
MPI_Barrier(MPI_COMM_WORLD);

Теперь нет вызовов new[], нет (ошибочных) вызовов free(). Существует очень мало, если вообще используется указатель. Так как вектор умеет себя уничтожать, утечек памяти нет.

person PaulMcKenzie    schedule 19.04.2014
comment
Я внес эти изменения, я согласен, что они определенно исправляют другие ошибки, но, к сожалению, они не решили мою проблему с ошибкой сегмента. - person Dan; 20.04.2014