Wydajność C i opcje kompilacji

Mam dwie podobne implementacje (java i c ++) dla trywialnego algorytmu, takiego jak sortowanie wyboru.

public interface SortingAlgorithm {

    public void sort(int[] a);
}

public class SelectionSort implements SortingAlgorithm {

    @Override
    public void sort(int[] a) {
        for (int i = 0; i < a.length; i++) {
            int lowerElementIndex = i;
            for (int j = i + 1; j < a.length; j++) {
                if (a[j] < a[lowerElementIndex]) {
                    lowerElementIndex = j;
                }
            }
            swap(a, lowerElementIndex, i);
        }
    }

    private void swap(int[] a, int i, int j) {
        if (i == j) {
            return;
        }
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

i c c:

inline void swap(int* a, int i, int j);

void s_sort(int* a, int size) {
  int i;
  for (i = 0; i < size; i++) {
    int lowerElementIndex = i, j;
    for (j = i + 1; j < size; j++) {
      if (a[j] < a[lowerElementIndex]) {
    lowerElementIndex = j;
      }
    }
    swap(a, lowerElementIndex, i);
  }
}

inline void swap(int* a, int i, int j) {
  if (i == j) {
    return;
  }
  int temp = a[i];
  a[i] = a[j];
  a[j] = temp;
}

Teraz próbowałem przetestować je na dużej tablicy (100000 losowych int). Wyniki na początku były java: ~ 17 sekund (skompilowane i wykonane z oracle jdk / jvm) c: ~ 22 sekund (skompilowane z gcc v4.8 bez jakiejkolwiek optymalizacji)

Oczywiście próbowałem zoptymalizować moją wersję c za pomocą cflagów. Wyniki są (Zgłaszam tylko cflagi): -O1: ~ 18.4

-O2: ~ 18,4

-O {3-9}: ~ 20,9

Moje pierwsze pytanie brzmi: które cflacs należy użyć do kompilacji?

Więc przeczytałem podręcznik gnu dotyczący optymalizacji. Dodanie -march = native nie pomogło. Po pewnym czasie spędzonym na próbowaniu innych opcji, wszedłem do opcji -fprofile-arcs. Dodanie go do moich flag sprawiło, że mój kod zakończył test w około 11 sekund! Jednak niektóre pliki pojawiły się w moich folderach: wyniki profilowania. Jak rozumiem, powinienem ich używać z prawdopodobieństwami -fbranch i przekompilować kod. Ponowna kompilacja wyników za ~ 18,5 sek.I o to naprawdę chcę zapytać.

Jak to możliwe, że mój program działa tak szybko, jeśli musi pisać pliki i zbierać informacje o profilowaniu, a zamiast tego działa 1,5 raza wolniej, gdy nie działa?

Zapomniałem wspomnieć, że jestem na starym komputerze z zainstalowanym procesorem Intel Celeron @ 2,8 GHz i linuxem (fedora 20 z xfce). Jeśli potrzebujesz innych informacji na temat sprzętu, po prostu zapytaj! ;)

Edytuj: Kod, którego używam do testu to:

Jawa:

public class Test {

    public static void main(String[] args) {
        int[] a = new int[100000];
        int[] a2 = new int[100000];
        for (int i = 0; i < a.length; i++) {
            a[i] = (int)(Math.random()*100000);
            a2[i] = a[i];
        }
        SelectionSort s = new SelectionSort();
        InsertionSort s1 = new InsertionSort();
        double start = System.nanoTime();
        s.sort(a);
        double end = System.nanoTime();
        double time = (end-start)/1000000000.0; 
        System.out.println("Selection: "+time);
        start = System.nanoTime();
        s1.sort(a2);
        end = System.nanoTime();
        time = (end-start)/1000000000.0;
        System.out.println("Insertion: "+time);
    }
}

I c:

#include "insertion_sort.h"
#include "selection_sort.h"
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main() {
  int max = 100000, i;
  srand(time(NULL));

  int array[100000], array2[100000];
  for(i=0; i<100000; i+=1) {
    array[i] = rand()%100000;
  }

  memcpy(array2, &array[0], 100000 * sizeof(int));

  clock_t inizio = clock();
  s_sort(array, max);
  clock_t fine = clock();
  float tempoEsecuzione = (float)(fine - inizio) / CLOCKS_PER_SEC;
  printf("Selection: %2.3f\n", tempoEsecuzione);

  inizio = clock();
  i_sort(array2, max);
  fine = clock();
  tempoEsecuzione = (float)(fine - inizio) / CLOCKS_PER_SEC;
  printf("Insertion: %2.3f\n", tempoEsecuzione);
  return 0;
}

Kod zawiera odniesienia do funkcji sortowania wstawiania, której nie uwzględniłem w pozostałej części pytania, ponieważ (zgodnie z oczekiwaniami) java działa wolniej niż c.

questionAnswers(4)

yourAnswerToTheQuestion