chillpenguin
chillpenguin

Reputation: 3079

for-loop optimization using pointer

I am trying to optimize code to run in under 7 seconds. I had it down to 8, and now I am trying to use pointers to speed up the code. But gcc gives an error when I try to compile:

.c:29: warning: assignment from incompatible pointer type .c:29: warning: comparison of distinct pointer types lacks a cast

Here is what I had before trying to use pointers:

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

#define N_TIMES     600000
#define ARRAY_SIZE   10000

int main (void)
{
    double  *array = calloc(ARRAY_SIZE, sizeof(double));
    double  sum = 0;
    int     i;

    double sum1 = 0;

    for (i = 0; i < N_TIMES; i++) {

        int     j;

        for (j = 0; j < ARRAY_SIZE; j += 20) {
            sum += array[j] + array[j+1] + array[j+2] + array[j+3] + array[j+4] + array[j+5] + array[j+6] + array[j+7] + array[j+8] + array[j+9];
            sum1 += array[j+10] + array[j+11] + array[j+12] + array[j+13] + array[j+14] + array[j+15] + array[j+16] + array[j+17] + array[j+18] + array[j+19];
            }

        }

    sum += sum1;

    return 0;
}

Here is what I have when I use pointers (this code generates the error):

int     *j;

        for (j = array; j < &array[ARRAY_SIZE]; j += 20) {
            sum += *j + *(j+1) + *(j+2) + *(j+3) + *(j+4) + *(j+5) + *(j+6) + *(j+7) + *(j+8) + *(j+9);
            sum1 += *(j+10) + *(j+11) + *(j+12) + *(j+13) + *(j+14) + *(j+15) + *(j+16) + *(j+17) + *(j+18) + *(j+19);
            }

How do I fix this error? Btw I don't want suggestions on alternative ways to try to optimize the code. This is a homework problem that has constraints about what I'm allowed to do. I think once I get this pointer thing fixed it will run under 7 seconds and i'll be good to go.

Upvotes: 0

Views: 2546

Answers (4)

user2693919
user2693919

Reputation: 1

" When you increment a pointer over an array, it uses the size of it's dereferenced element to know how far in memory to move. Moving with an int over an array of doubles will lead to issues ".

To avoid your warn: do the below one

for (j= (int *)array; j < (int *)&array[ARRAY_SIZE]; j += 20)

Upvotes: 0

Edwin Buck
Edwin Buck

Reputation: 70899

I'd be greatly surprised if moving from an array representation to a pointer representation would yield much (if any) speedup, as both are memory addresses (and memory offsets) in the final outputted code. Remember, the array representation is actually a pointer representation in different clothing too.

Instead, I'd look towards one of two techniques:

  1. Embedded MMX representations, to do multiple addition operations within the same register, under the same clock cycle. Then, you need one operation near the end to combine the high double with the low double.

  2. Scatter / Gather algorithims to spread the addition operation across multiple cores (nearly every CPU these days has 4 cores available, if not 16 pseudo-cores (a la hyper-threading))

Beyond that, you can do a few attempts at cache analysis, and at storing intermediates in different registers. There seems to be a deep chain of additions in each of your computations. Breaking them up might yield the ability to spread the on-cpu storage across more registers.

Most operations become memory bound. 20 is a really strange boundary for loop unrolling. Doubles probably are 16 bits, so 20 doubles is 320 bits, which is probably not aligned to your memory cache line size. Try making sure that multiples of your unrolled loop align cleanly with your architecture's level 1 cache, and you might avoid a page fault as you read across cache boundaries. Doing so will speed up your program by some (but who knows how much).

Upvotes: 0

lsiebert
lsiebert

Reputation: 667

C is a statically typed language, and comparisons across pointer types will give you errors. There is some implicit casting in certain cases, like if you compare a double to an int, because comparing numbers is a common operation. Comparing pointers of different types isn't.

Further, when you increment a pointer over an array, it uses the size of it's dereferenced element to know how far in memory to move. Moving with an int over an array of doubles will lead to issues.

A double will move farther then an int, so you will get more interations with an int pointer anyway.

You could explicitly cast things, but really you should be using a double * for an array of doubles.

Upvotes: 0

Billy ONeal
Billy ONeal

Reputation: 106530

comparison of distinct pointer types lacks a cast

This means that you tried to compare a pointer of one type to a pointer of another type, and did so without a cast.

double  *array = calloc(ARRAY_SIZE, sizeof(double));
int     *j;

Pointers to double and pointers to int are not directly comparable. You aren't allowed to compare j to array for this reason. Perhaps you meant to declare j as a pointer to double ?

Upvotes: 2

Related Questions