Home > Software design >  Why isn't my function (using multithreading) correctly taking the average?
Why isn't my function (using multithreading) correctly taking the average?

Time:11-03

The relevant part of the code is this:

void *calculate_average(void *param)
{
        int count = *(int *)param;
    int i;
    double sum;

    average = 0.000000;

    for (i=1l; i<count; i  )
        sum  = list[i];
    
    average = (double)(sum / count);
    pthread_exit(0);
}

The only purpose of this function is to take an average of numbers stored in the list, and assign that value to the double average, which is managed and eventually returned by the parent thread. The list of numbers is entered on the invocation of the program and immediately stored in the list.

An example case is the set of numbers {54 15 25 45 60 93 68 57}. This set of numbers has the average 52.125. The program, when run, outputs an average of 45.375. We're required to use the gcc compiler, so it's not as if I have a full debug suite available for use. I'm unsure of the full nature of the issue, any help would be greatly appreciated.

CodePudding user response:

As mentioned in the comments above, you're using global and local variables, not wrong but error-prone. As you can pass an argument to the thread starting function, making good use of it, is of huge benefit.

e.g.

//data struct which is used to provide a thread function
//with a range of data and a field called 'average' to return
//the result
struct thread_data {
    int *begin; //inclusive
    int *end;   //exclusive
    double average; //result
};

void* calculate_average(void *param)
{
    struct thread_data *data = (struct thread_data*) param; //cast
    int sum = 0; //initialize with 0
    for (int *ptr = data->begin; ptr < data->end;   ptr) //for each element
        sum  = *ptr; //add element value to sum
    data->average = (double) sum / (data->end - data->begin); //take the average
    return NULL; //return NULL or some other meaningful value
}

int main()
{
    int *arr; //some int values
    struct thread_data data[] = { //create partitions
        {.begin = arr,     .end = arr   n},
        {.begin = arr   n, .end = arr   m},
        /* ... */
    };
    //then for each thread, pass &data[i] as argument 
    //to the thread starting function
    //e.g. pthread_create(&thread[i], NULL, calculate_average, &data[i]
}

As you can see, no global variables are used, therefore no data race conditions. The list has been partitioned and passed separately to the individual threads. Each data partition has its own average field, which then can be used to take the average of the whole list.

  • Related