1. ホーム
  2. スクリプト・コラム
  3. その他

[解決済み】異なるサイズの整数からポインタにキャストする、pthreadコード

2022-01-02 13:50:03

質問

pthreadsを使用した行列の乗算のコードですが、"cast to pointer from integer of different size "というエラーが発生します。

私はpthreadの初心者で、今まで作ったものは以下の通りです。

#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);
}

この行でエラーが発生しました。

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

解決するには?

スレッドに整数を渡すためにハックを使用するのは間違っています。x86_32では整数が4バイト、ポインタが4バイト(x86_64では8バイト)なので、整数型からポインタ型に変換して、データを失うことなくint型に戻すことができる、というのがその背後にある考え方です。しかし、ポインタと整数が同じサイズである保証はありません。C言語規格では ではなく がこれを指定します。

を変換しているため、コンパイラは警告を返します。 cast to pointer from integer of different size に変更します。 int というように、サイズが異なる場合があります(ただし、あなたのマシンでは同じサイズです)。

pthead_create 関数で int 型を void* 型に変換する際に、整数型に変換し直す必要がありますが、このコードに誤りがあります。つまり、この行は間違っています。

プレ {コード

であるべきです。

void *

スレッド関数の引数が0である場合の例について考えてみましょう。

int *id=(int *)s;

これはアドレスゼロへのポインタです。これを参照しようとすると、セグメンテーションフォールトが発生する可能性があります。

を使用するのが最適です。 intptr_t という型があります。この型は、どのアーキテクチャでも同じサイズのポインタ(intではない)を持っています。次のように定義されています.

voidポインタから変換された値を保持することができる整数型 と比較される値でその型に変換され、元に戻ります。 は元のポインタと等しい。

だから、こんなこともできるんです。

int id = (int)s; 

(このサンプルコードは、. から引用しています。 整数を void ポインタにキャストするには? )

ただし,int 型のサイズは,int 型と同じサイズである保証はありません。 s=0; therefore ---> *id=(int*)0; // Null pointer

#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);

intptr_t

  • float **Aa, **Bb, **Cc;
  • start が配列の制限値を超えている。行列の行が連続したメモリ領域に割り当てられていない。
  • {を使用します。 スレッド関数が行列の一部分に対して動作している場合、行列 A と B のすべての値を調べる必要はありません。

行列の乗算のアルゴリズムがおかしいので、コードを書き直すことを検討します。