0

既存のシリアル行列乗算コードで pthreads を使用したいと考えています。私の目標は、単純にスピードアップを実現するために、pthreads を使用して実行時間を短縮することです。しかし、その時点で私は立ち往生しています。元のシリアル コードは問題なく動作し、1000x1000 の正方行列の乗算を約 15 秒で完了しました。しかし、現在の pthreads プログラムを実行すると、セグメンテーション違反が発生します。これが私のコードです:

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

int SIZE, NTHREADS;
int **A, **B, **C;

void init()
{
    int i, j;

    A = (int**)malloc(SIZE * sizeof(int *));
    for(i = 0; i < SIZE; i++)
        A[i] = malloc(SIZE * sizeof(int));

    B = (int**)malloc(SIZE * sizeof(int *));
    for(i = 0; i < SIZE; i++)
        B[i] = malloc(SIZE * sizeof(int));

    C = (int**)malloc(SIZE * sizeof(int *));
    for(i = 0; i < SIZE; i++)
        C[i] = malloc(SIZE * sizeof(int));

    srand(time(NULL));

    for(i = 0; i < SIZE; i++) {
        for(j = 0; j < SIZE; j++) {
            A[i][j] = rand()%100;
            B[i][j] = rand()%100;
        }
    }
}

void mm(int tid)
{
    int i, j, k;
    int start = tid * SIZE/NTHREADS;
    int end = (tid+1) * (SIZE/NTHREADS) - 1;

    for(i = start; i <= end; i++) {
        for(j = 0; j < SIZE; j++) {
            C[i][j] = 0;
            for(k = 0; k < SIZE; k++) {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}

void *worker(void *arg)
{
    int tid = *((int *) arg);
    mm(tid);
}

int main(int argc, char* argv[])
{
    pthread_t* threads;
    int rc, i;

    if(argc != 3)
    {
        printf("Usage: %s <size_of_square_matrix> <number_of_threads>\n", argv[0]);
        exit(1);
    }

    SIZE = atoi(argv[1]);
    NTHREADS = atoi(argv[2]);
    init();
    threads = (pthread_t*)malloc(NTHREADS * sizeof(pthread_t));

    clock_t begin, end;
    double time_spent;


    begin = clock();

    for(i = 0; i < NTHREADS; i++) {
        rc = pthread_create(&threads[i], NULL, worker, (void *)i);
        assert(rc == 0);
    }

    for(i = 0; i < NTHREADS; i++) {
        rc = pthread_join(threads[i], NULL);
        assert(rc == 0);
    } 

    end = clock();

    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("Elapsed time: %.2lf seconds.\n", time_spent);

    for(i = 0; i < SIZE; i++)
        free((void *)A[i]);
    free((void *)A);

    for(i = 0; i < SIZE; i++)
        free((void *)B[i]);
    free((void *)B);

    for(i = 0; i < SIZE; i++)
        free((void *)C[i]);
    free((void *)C);

    free(threads);

    return 0;
}

誰かが私の pthreads プログラムを実行するのを手伝ってくれて、スピードアップを達成できたら嬉しいです。

4

1 に答える 1

3

現在のコードでは、次を使用してインデックスを取得する必要があります

int tid = (int)arg;

(あなたのコードは効果的にループ カウンターをアドレスとして扱い、0 またはその付近のアドレスを逆参照しています。これらのアドレスはプロセスで読み取れないか、適切に整列されないため、セグ フォールトが発生します)

上記の変更により、うまくいくかもしれませんが、 anintを a として渡すことvoid*は完全に正しいわけではないことに注意してください。sizeof(int) <= sizeof(void*)可能性が高いが、真実であるとは保証されていないことに依存します。これを気にする場合は、代わりに各スレッドに渡すデータにメモリを割り当てるか、アドレスを渡してi同期を含めてpthread_create、スレッドがスケジュールされてその引数を読み取るまで各呼び出しの後に待機するようにすることができます。

于 2013-04-12T14:56:10.210 に答える