J'ai ce code pour la multiplication de matrice, en utilisant pthreads, mais j'obtiens l'erreur "cast to pointeur à partir d'un entier de taille différente"
Je ne sais pas ce qui ne va pas. Je suis novice en lecture, et voici ce que j'ai fait jusqu'à présent:
#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);
}
l'erreur à cette ligne:
pthread_create(&thread_id[i], NULL, prod, (void *)i);
Vous utilisez à tort un hack pour passer un entier à un thread. L'idée derrière ce que vous faites est qu'un entier est 4 octets et un pointeur 4 octets en x86_32 (8 octets en x86_64) afin que je puisse convertir un type entier en type pointeur puis le reconvertir en type int sans perdre Les données. Cela fonctionne dans la majorité des scénarios, mais rien ne garantit qu'un pointeur et un entier ont la même taille. La norme C ne spécifie pas ceci pas.
Le compilateur renvoie un avertissement parce que vous convertissez une int
en void *
qui peut avoir une taille différente (mais, en fait, sur votre ordinateur, ils ont la même taille).
Il y a une erreur dans votre code. Lorsque vous convertissez l'int en un void * appelant la fonction pthead_create, vous devez le reconvertir en un type entier. Donc, cette ligne est fausse:
int *id=(int *)s;
cA devrait etre :
int id = (int)s;
Prenons cet exemple où l'argument de la fonction de thread est zéro.
s=0; therefore ---> *id=(int*)0; // Null pointer
Ceci est un pointeur sur l'adresse zéro. Lorsque vous essayez de la déférer, vous obtiendrez probablement une erreur de segmentation.
La meilleure façon de procéder consiste à utiliser le type intptr_t. Ce type a la même taille qu'un pointeur (pas int) dans toutes les architectures. Il est défini comme suit:
Type entier capable de contenir une valeur convertie à partir d'un pointeur vide et ensuite être reconverti en ce type avec une valeur qui compare égal au pointeur d'origine.
Donc, vous pouvez faire quelque chose comme ça:
#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);
(Cet exemple de code provient de: Comment convertir un entier en pointeur vide? )
Cependant, rien ne garantit que la taille de int est identique à celle de intptr_t
, mais il est très peu probable que certaines données soient perdues lors du processus de conversion.
MODIFIER
Erreurs supplémentaires:
float **Aa, **Bb, **Cc;
ne sont pas initialisés. start
et end
dépasse la limite du tableau. Les lignes de la matrice ne sont pas allouées dans des zones de mémoire consécutives. J'envisagerais de réécrire le code pour la multiplication de matrice parce que l'algorithme est faux.
Pour y parvenir, utilisez la variable "i" (consultez http://man7.org/linux/man-pages/man3/pthread_create.3.html ):
pthread_create(&thread_id[i], NULL, prod, (void *)&i);
Vous souhaitez convertir un entier, un court ou un caractère et définir un pointeur sur cette valeur, utilisez l'appel reinterpret_cast (). Nous avions l'habitude de (void *) la valeur et les anciens compilateurs étaient contents, mais les nouvelles versions, par exemple g ++ 4.8.5, savent que la valeur n'est pas la bonne taille pour un pointeur. reinterpret_cast est comme un casting, mais il a été redimensionné pour que la compilation ne se plaint pas.
Par exemple:
int i = 3;
pointer void * ptr;
ptr = (void*)i; // will generate the warning
ptr = reinterpret_cast<void*>(i); // No warning is generated
Exemple X11 qui récupère un caractère dans addr, puis lui attribue XTPOINTER.
val = (XTPOINTER)(*(char*)toVal.addr); // warning
val = reinterpret_cast<XTPOINTER>(*(short*)toVal.addr); // No warning