Benchmarking C bubblesort performance compared to Julia

Viewed 259

I wanted to create a formal comparison between C and Julia performance. For this purpose I wanted to compare different sorting algorithms, starting with the bubble. In Julia I wrote it like:

using BenchmarkTools

function bubble_sort(v::AbstractArray{T}) where T<:Real
    for _ in 1:length(v)-1
        for i in 1:length(v)-1
            if v[i] > v[i+1]
                v[i], v[i+1] = v[i+1], v[i]
            end
        end
    end
    return v
end

v = rand(Int32, 100_000)
@timed bubble_sort(_v)

In the case of C code (I don't know to program in C so I apologize for the code):

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static void swap(int *xp, int *yp){
    int temp = *xp;
    *xp = *yp;
    *yp = temp;
}

void bubble_sort(int arr[], int n){
    int i, j;
    for (j = 0; j < n - 1; j++){
        for (i = 0; i < n - 1; i++){
            if (arr[i] > arr[i+1]){
                swap(&arr[i], &arr[i+1]);
            }
        }
    }
}

int main(){
    int arr_sz = 100000;
    int arr[arr_sz], i;
    for (i = 0; i < arr_sz; i++){
        arr[i] = rand();
    }
    double cpu_time_used;
    clock_t begin = clock();
    bubble_sort(arr, arr_sz);
    clock_t end = clock();
    cpu_time_used = ((double) (end - begin)) / CLOCKS_PER_SEC;
    printf("time %f\n", cpu_time_used);
    return 0;
}

The performance difference is (in my computer):

Julia C
20s ~50s

I suppose that I have a big mistake in the C code, but I am not able to find it out, or is just Julia faster in loops?

Update: performance optimization

  • Changed the type to int32 in Julia so it is the same as C
  • swap method as static (+1s improvement on average)
  • compiling optimization (detailed bellow)

Instead of gcc main.c, I've used different optimization flags, as also the clang compiler. Results:

Time (s)
Julia 19.13
gcc -O main.c 47.58
gcc -O1 main.c 15.98
gcc -O2 main.c 19.52
gcc -O3 main.c 19.20
gcc -Os main.c 17.72
clang -O0 main.c 51.59
clang -O1 main.c 16.78
clang -O2 main.c 13.53
clang -O3 main.c 13.57
clang -Ofast main.c 12.39
clang -Os main.c 18.85
clang -Oz main.c 15.64
clang -Og main.c 16.37
1 Answers

It seems like this question may have been reopened after you discovered that your initial measurements were taken on code compiled for debugging, rather than fully optimised, with different sets of data, different compiler platforms and different integer representations.

I suppose that I have a big mistake in the C code, but I am not able to find it out, or is just Julia faster in loops?

I can answer this somewhat cringy (in my opinion) double-barreled question with a quote from the C standard: "The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant." In short, there's no speed in C; that's an attribute that occurs in implementations of C. We can't reproduce your speed without having your implementation (including your hardware, for example).

It's very possible that Julia has similar clauses in her spec. The gist is: some nifty optimisations may determine that your sorted arrays don't have any necessary side-effects and so those may theoretically be optimised away. I'd expect both programs to output somewhere near 0.0 in that case. This is your perfectly optimal compiler; one that spots code that has no actual impact upon the logic of the program, and optimises away the dead code.

We haven't always had loop-invariant code motion, and so it stands to reason that there may be a fifth element here: your compilers version. You'll probably get different statistics if the underlying llvm is different, for example:

LLVM 11 tends to take 2x longer to compile code with optimizations, and as a result produces code that runs 10-20% faster (with occasional outliers in either direction), compared to LLVM 2.7 which is more than 10 years old.

-- source

Perhaps one day you'll update this question with output that reads 0.0s for both programs. Then this question has truly lost its point.


It's hard to tell what further is being asked here, @cbk. The comments section managed to reduce the runtime for the C program significantly with those four improvements. The question kinda doesn't even make sense here anymore, because it largely cancels itself out by answering itself at the end.

Perhaps this is just one of those cases where a newcomer ought to have answered their own question with an answer (you can do that), rather than rotting the question with edits that answer it... Nonetheless, it's a question that now shows up unanswered in the list of questions. I'd vote to close for the reason "The question should include more details", but I suspect then you might include an example of compilation halted after assembly generation, when OP seems to have glossed over the solution, the details we need are more along the lines of "What didn't you understand about these comments that answer your original question?" and yet the question has varied so much in apparent meaning... Are we gonna have a close/reopen war?

Related