I have this code for matrix multiplication, using pthreads, but I get the error "cast to pointer from integer of different size"

I don't know what is wrong.I am new to pthread, and this is what I have made so far:

#include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/time.h> #include <pthread.h> #define NTHREADS 4 int dim ; pthread_mutex_t m; /* Mutex protecting the sum value */ pthread_t thread_id[NTHREADS]; /* Thread ids */ float **A, **B, **C; void *prod (void *s){ int *id=(int *)s; int idd=*id; /* Define local variables */ int i,j,k, start, end, len ; float **Aa, **Bb, **Cc; start = dim*idd; /* Start of this threads slice of the vectors */ end = start + dim; /* End of the slice */ for (i = 0 ; i < dim; i++) { for (j = 0; j < dim; j++) { Cc[i][j] = 0; for (i=start; i<end ; i++) { Cc[i][j] += Aa[i][k] * Bb[k][j]; } } } pthread_mutex_lock (&m); /* Lock the mutex */ C[i][j] += Cc[i][j]; /* Update the shared variable */ pthread_mutex_unlock (&m); /* Unlock the mutex */ pthread_exit(NULL); /* Done! */ } int main ( int argc, char *argv[] ) { void *status; float **A, **B, **C; int i,j,k; if ( argc == 2) dim = atoi(argv[1]); // get the dimension of the matrix // from the command prompt else dim = 128; A = (float **)malloc(sizeof(float*)*dim); B = (float **)malloc(sizeof(float*)*dim); C = (float **)malloc(sizeof(float*)*dim); for (i = 0 ; i < dim; i++) { A[i] = (float *)malloc(sizeof(float)*dim); B[i] = (float *)malloc(sizeof(float)*dim); C[i] = (float *)malloc(sizeof(float)*dim); } for (i=0; i<dim; i++) { for (j = 0 ; j < dim; j++) { A[i][j]=rand(); B[i][j]=rand(); } } struct timeval t1, t2; gettimeofday(&t1, NULL); // you need to parallelize this // perform the multiplication for(i=0;i<NTHREADS;i++) { pthread_create(&thread_id[i], NULL, prod, (void *)i); } /* Wait on the other threads */ for(i=0;i<NTHREADS;i++) { pthread_join(thread_id[i], &status); } gettimeofday(&t2, NULL); double t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec ) / 1000000.0; // take the difference and report it in seconds printf("execution time %f seconds\n",t); } 

the error at this line:

pthread_create(&thread_id[i], NULL, prod, (void *)i); 
15

3 Answers

You are wrongly using an hack to pass an integer to a thread. The idea behind what you are doing is an integer is 4 bytes and a pointer is 4 bytes in x86_32 (8 bytes in x86_64) so I can convert an integer type to a pointer type and then convert it back to an int type without losing any data. This works in the majority of the scenarios, but there is not guarantee that a pointer and an integer have the same size. The C standard does not specify this.

The compiler returns a warning because you are converting an int to void * which may have different size, ( but in fact in your machine they have the same size).

There is a error in you code, when you convert the int to a void* calling the pthead_create function, you should convert it back to an integer type. So, this line is wrong :

int *id=(int *)s; 

it should be :

int id = (int)s; 

Consider this example where the argument for the thread function is zero.

s=0; therefore ---> *id=(int*)0; // Null pointer 

This is a pointer to the address zero. When you try to deference it, you will likely get an segmentation fault.

The best way to do this is by using the intptr_t type. This type has the same size of a pointer (not int) in every architecture. It is defined as follows :

Integer type capable of holding a value converted from a void pointer and then be converted back to that type with a value that compares equal to the original pointer.

So you can do something like this:

#include <stdint.h> void *threadfunc(void *param) { int id = (intptr_t) param; ... } int i, r; r = pthread_create(&thread, NULL, threadfunc, (void *) (intptr_t) i); 

(This example code has been taken from : How to cast an integer to void pointer?)

However, there is not guarantee that the size of int is the same of the size of intptr_t, but it's really unlikely that some data is lost in the conversion process.

EDIT

Additional errors :

  • float **Aa, **Bb, **Cc; are not initialised.
  • start and end exceeds the limit of the array. The matrix rows are not allocated in consecutive memory areas.
  • if the thread function is working on a chunks of the matrix, there is not point to go through all the values of the matrix A and B. You might want only the internal loop which, in theory, should work on the part of matrix assigned to it.

I would consider to rewrite the code for the matrix multiplication because the algorithm is wrong.

4

Correct way to achieve this is by referencing the variable "i" (check ):

pthread_create(&thread_id[i], NULL, prod, (void *)&i); 
2

You want to cast integer, short, or char and set a pointer to that value use the reinterpret_cast() call. We used to just (void*) the value and the older compilers were happy, but the new versions, for example g++ 4.8.5, know the value is not the right size for a pointer. reinterpret_cast is just like a cast but it resized it so the compile doesn't complain.

For example:

int i = 3; pointer void * ptr; ptr = (void*)i; // will generate the warning ptr = reinterpret_cast<void*>(i); // No warning is generated 

X11 example getting a character out of addr and then setting XTPOINTER to it.

val = (XTPOINTER)(*(char*)toVal.addr); // warning val = reinterpret_cast<XTPOINTER>(*(short*)toVal.addr); // No warning 
0

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy