compute_ranks function I've been working on optimizing such as loop unrolling, is there anything I can do to optimize this code to make it run faster/in less cycles?

void compute_ranks(float *F, int N, int *R, float *avg, float *passing_avg, int *num_passed) {
    int i, j;
    *num_passed = 0;
    *avg = 0.0;
    *passing_avg = 0.0;

    // init ranks
    for (i = 0; i &lt; N; i++) {
        R[i] = 1;
    }

    // compute ranks
    for (i = 0; i &lt; N; i++) {
        for (j = 0; j &lt; N; j++) {
            if (F[i] &lt; F[j]) {
                R[i] += 1;
            }
        }
    }

    // compute averages
    for (i = 0; i &lt; N; i++) {
        *avg += F[i];
        if (F[i] &gt;= 50.0) {
            *passing_avg += F[i];
            *num_passed += 1;
        }
    }

    // check for div by 0
    if (N &gt; 0) *avg /= N;
    if (*num_passed) *passing_avg /= *num_passed;

} // compute_ranks


I did this for the first one

or (i = 0; i &lt; N; i += 5) {
        R[i] = 1;
        R[i+1] = 1;
        R[i+2] = 1;
        R[i+3] = 1;
        R[i+4] = 1;
    }*/


Is there a way to not use pointers or anything really to make this more optimized?
One possible optimization is to use local variables instead of directly writing to the out parameters. So instead of:

// compute averages
for (i = 0; i &lt; N; i++) {
    *avg += F[i];
    if (F[i] &gt;= 50.0) {
        *passing_avg += F[i];
        *num_passed += 1;
    }
}


you write:

int l_num_passed = 0;
float l_avg = 0.0;
float l_passing_avg = 0.0;

// compute averages
for (i = 0; i &lt; N; i++) {
    l_avg += F[i];
    if (F[i] &gt;= 50.0) {
        l_passing_avg += F[i];
        l_num_passed += 1;
    }
}

*num_passed = l_num_passed;
*avg = l_avg;
*passing_avg = l_passing_avg;


That way the compiler can use fast registers. If you directly write to the out parameter within the loop, the compiler cannot use registers as it must stay on the defensive side by assuming that avg could point to the same memory location as passing_avg or even num_passed.

This unfortunate feature of C and C++ is known as pointer aliasing and often prevents the compiler from making effective use of registers.

You can also use local variables for the other loop. Instead of:

// compute ranks
for (i = 0; i &lt; N; i++) {
    for (j = 0; j &lt; N; j++) {
        if (F[i] &lt; F[j]) {
            R[i] += 1;
        }
    }
}


write:

float fi;
int rank;

// compute ranks
for (i = 0; i &lt; N; i++) {
    fi = F[i];
    rank = 1;
    for (j = 0; j &lt; N; j++) {
        if (fi &lt; F[j]) {
            rank += 1;
        }
    }
    R[i] = rank;
}