время работы уже отсортированного массива, сортируемого алгоритмом сортировки выбором, по сравнению со временем сортировки массива с обратной сортировкой

Я пытаюсь выяснить время выполнения алгоритма сортировки выбором для сортировки уже отсортированного массива (например, 1,2,3,4,5,..) и время его использования для сортировки массива в обратном порядке (например, 5 ,4,3,2..). Странная вещь, которую я обнаружил, заключается в том, что на моем компьютере сортировка уже отсортированного массива занимает больше времени, чем сортировка массива в обратном порядке. Из того, что я узнал, я думаю, что должно быть наоборот.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void selectionsort(int A[], int n) {
    int min;
    for (int i = 0; i < n - 1; i++) {
        min = i;
        for (int k = i + 1; k < n; k++) {
            if (A[k] < A[min]) {
                min = k;
            }
        }
        int temp = A[i];
        A[i] = A[min];
        A[min] = temp;
    }
}

void sort(int A[], int n) {
    for (int i = 0; i < n; i++) {
        A[i] = i + 1;
    }
}

void resver_sort(int A[], int n) {
    for (int i = 0; i < n; i++) {
        A[i] = n - i;
    }
}

int main() {
    clock_t start, end;
    double cpu_time_used;

    int A[20000] = { 0 };
    int B[40000] = {0};
    int C[100000] = {0};

    printf("Selection Sort, Sorted Array\n");

    sort(A, 20000);
    start = clock(); // start the clock
    selectionsort(A, 20000);
    end = clock(); // stop the clock
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; // calculate the actual time used
    printf("array size:20000 time:%f\n", cpu_time_used);

    sort(B, 40000);
    start = clock();
    selectionsort(B, 40000);
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("array size:40000 time:%f\n", cpu_time_used);

    sort(C, 100000);
    start = clock();
    selectionsort(C, 100000);
    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("array size:100000 time:%f\n", cpu_time_used);

    printf("Selection Sort, reverse sorted Array\n");

    resver_sort(A, 20000);
    start = clock(); 
    selectionsort(A, 20000);
    end = clock(); 
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; 
    printf("array size:20000 time:%f\n", cpu_time_used);

    resver_sort(B, 40000);
    start = clock();
    selectionsort(B, 40000);
    end = clock();  
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("array size:40000 time:%f\n", cpu_time_used);

    resver_sort(C, 100000);
    start = clock();    
    selectionsort(C,100000);
    end = clock();   
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("array size:100000 time:%f\n", cpu_time_used);
}

Результат

Selection Sort, Sorted Array
array size:20000 time:0.530281
array size:40000 time:2.109836
array size:100000 time:13.197117
Selection Sort, reverse sorted Array
array size:20000 time:0.500338
array size:40000 time:2.016468
array size:100000 time:12.830447
Program ended with exit code: 0

Первый, который представляет собой уже отсортированный массив, занимает больше времени. Это не имеет смысла. Я потратил много времени на отладку и попытки распечатать эти массивы, чтобы изучить их, но так и не понял.


person Joji    schedule 26.02.2017    source источник
comment
Сделайте это несколько тысяч раз и получите среднее время. Также проведите такие измерения на оптимизированных сборках.   -  person Some programmer dude    schedule 26.02.2017
comment
И не могли бы вы рассмотреть возможность повторного отступа вашего кода, чтобы его можно было действительно прочитать.   -  person Antti Haapala    schedule 26.02.2017
comment
@Antti Haapala извините, я не знал, что это нечитаемо для вас. Я пересмотрел. :)   -  person Joji    schedule 26.02.2017
comment
Спасибо, теперь намного лучше!   -  person Antti Haapala    schedule 26.02.2017
comment
Хорошо, я протестировал это. С -03 время работы сократилось на 67 %. Кроме того, первая операция сортировки выполняется медленнее, чем вторая операция сортировки, независимо от того, что происходит раньше. Должен иметь какое-то отношение к кэшированию и прогнозированию ветвлений.   -  person Antti Haapala    schedule 26.02.2017


Ответы (1)


В вашем коде есть несколько проблем:

  • вы не включаете <stdio.h> и <time.h>
  • вы не определяете массивы B и C. Я предлагаю вам использовать массивы со статическим или динамическим (кучей) хранилищем, а не с автоматическим, чтобы избежать переполнения стека.
  • функция sort имеет переполнение буфера в: for (int i = 0; i <= n; i++) должно быть i < n.

Что касается таймингов, ваша функция сортировки selectionsort выполняет точно такое же количество сравнений и перестановок, за исключением результата, поэтому тайминги должны быть близкими, отличаясь только результатом A[k] < A[min]. В отсортированном случае этот тест всегда ложный, а для другого случая он меняется, количество истинных случаев линейно уменьшается от n - 2 до 0. В зависимости от того, как генерируется код для этого цикла и насколько эффективна функция прогнозирования ветвлений процессора, вы можете получить небольшое преимущество в пользу того или иного варианта. Об этом вам скажет только тщательный расчет времени. Судя по вашим результатам, стоимость ветки никогда не превышала компенсации за дополнительный магазин min = i.

Ваши тайминги на самом деле довольно близки (разница менее 6%). Я получаю одинаковые результаты, но несколько запусков одной и той же программы дают время, которое различается на один и тот же порядок величины... что затрудняет получение определенных выводов.

Различные компиляторы и разные ЦП могут дать противоположный результат.

Первоначальный проход для проверки уже отсортированного ввода имеет смысл, поскольку он очень мало увеличивает время неэффективной сортировки, такой как insertionsort. это сделало бы эти особые случаи почти мгновенными: 0.00001, 0.00002 и 0.00005 для вашего примера.

Более эффективные алгоритмы сортировки также затмят это время: пирамидальная сортировка, сортировка слиянием, быстрая сортировка, сортировка по основанию должны быть в 100–1000 раз быстрее при заданных размерах.

person chqrlie    schedule 26.02.2017