测量多线程C程序的速度(使用Pthreads实现)

时间:2017-01-01 12:42:02

标签: c multithreading pthreads

我目前有一个使用Pthreads编码的多线程C程序,它使用2个线程。我想增加号码。线程和测量速度加快。我想以自动方式运行我的代码,其中no。使用的线程不断增加,我想以图形方式显示我的代码的运行时间。如果我能够了解如何这样做,特别是如何自动化整个过程并以图形方式绘制它,我会很喜欢它。这是我的代码:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 2
#define VECTOR_SIZE 40

struct DOTdata
{
    /* data */
    long X[VECTOR_SIZE];
    long Y[VECTOR_SIZE];
    long sum;
    long compute_length;
};

struct DOTdata dotstr;
pthread_mutex_t mutex_sum;

void *calcDOT(void *);

int main(int argc, char *argv[])
{
    long vec_index;

    for(vec_index = 0 ; vec_index < VECTOR_SIZE ; vec_index++){
        dotstr.X[vec_index] = vec_index + 1;
        dotstr.Y[vec_index] = vec_index + 2; 
    }

    dotstr.sum = 0;
    dotstr.compute_length = VECTOR_SIZE/NUM_THREADS;

    pthread_t call_thread[NUM_THREADS];
    pthread_attr_t attr;
    void *status;

    pthread_mutex_init(&mutex_sum, NULL);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    long i;

    for(i = 0 ; i < NUM_THREADS ; i++){
        pthread_create(&call_thread[i], &attr, calcDOT, (void *)i);
    }

    pthread_attr_destroy(&attr);

    for (i = 0 ; i < NUM_THREADS ; i++){
        pthread_join(call_thread[i], &status);
    }

    printf("Resultant X*Y is %ld\n", dotstr.sum);
    pthread_mutex_destroy(&mutex_sum);
    pthread_exit(NULL);
}

void *calcDOT(void *thread_id)
{
    long vec_index;
    long start_index;
    long end_index;
    long length;
    long offset;
    long sum = 0;

    offset = (long)thread_id;
    length = dotstr.compute_length;

    start_index = offset * length;
    end_index = (start_index + length) - 1;

    for(vec_index = start_index ; vec_index < end_index ; vec_index++){
        sum += (dotstr.X[vec_index] * dotstr.Y[vec_index]);
    }

    pthread_mutex_lock(&mutex_sum);
    dotstr.sum += sum;
    pthread_mutex_unlock(&mutex_sum);

    pthread_exit((void *)thread_id);

}

我想增加我的NUM_THREADS参数并在每次增量后运行它,记录每次增量后的执行时间并绘制执行时间与线程数的图表。

1 个答案:

答案 0 :(得分:2)

我尝试了一种天真的方法,增加线程数,用time.h计时并用gnuplot绘制。每次迭代我们将线程数加倍,然后打印迭代时间。我们使用gnuplot显示一个图表,其中x轴为线程数,y轴为执行时间

enter image description here

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

#define NUM_THREADS 2
#define VECTOR_SIZE 40

struct DOTdata {
    /* data */
    long X[VECTOR_SIZE];
    long Y[VECTOR_SIZE];
    long sum;
    long compute_length;
};

struct DOTdata dotstr;
pthread_mutex_t mutex_sum;

void *calcDOT(void *);

int main(int argc, char *argv[]) {
    double xvals[VECTOR_SIZE / NUM_THREADS];
    double yvals[VECTOR_SIZE / NUM_THREADS];
    int index = 0;
    for (int count = NUM_THREADS; count < VECTOR_SIZE / NUM_THREADS; count = count * 2) {

        clock_t begin = clock();

        long vec_index;

        for (vec_index = 0; vec_index < VECTOR_SIZE; vec_index++) {
            dotstr.X[vec_index] = vec_index + 1;
            dotstr.Y[vec_index] = vec_index + 2;
        }

        dotstr.sum = 0;
        dotstr.compute_length = VECTOR_SIZE / count;

        pthread_t call_thread[count];
        pthread_attr_t attr;
        void *status;

        pthread_mutex_init(&mutex_sum, NULL);

        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

        long i;

        for (i = 0; i < count; i++) {
            pthread_create(&call_thread[i], &attr, calcDOT, (void *) i);
        }

        pthread_attr_destroy(&attr);

        for (i = 0; i < count; i++) {
            pthread_join(call_thread[i], &status);
        }

        printf("Resultant X*Y is %ld\n", dotstr.sum);
        pthread_mutex_destroy(&mutex_sum);
        clock_t end = clock();
        double time_spent = (double) (end - begin) / CLOCKS_PER_SEC;

        printf("time spent: %f NUM_THREADS: %d\n", time_spent, count);
        xvals[index] = count;
        yvals[index] = time_spent;
        index++;
    }

    FILE * gnuplotPipe = popen ("gnuplot -persistent", "w");

    fprintf(gnuplotPipe, "plot '-' \n");

    for (int i = 0; i < VECTOR_SIZE / NUM_THREADS; i++)
    {
        fprintf(gnuplotPipe, "%lf %lf\n", xvals[i], yvals[i]);
    }

    fprintf(gnuplotPipe, "e");


    pthread_exit(NULL);
}

void *calcDOT(void *thread_id) {
    long vec_index;
    long start_index;
    long end_index;
    long length;
    long offset;
    long sum = 0;

    offset = (long) thread_id;
    length = dotstr.compute_length;

    start_index = offset * length;
    end_index = (start_index + length) - 1;

    for (vec_index = start_index; vec_index < end_index; vec_index++) {
        sum += (dotstr.X[vec_index] * dotstr.Y[vec_index]);
    }

    pthread_mutex_lock(&mutex_sum);
    dotstr.sum += sum;
    pthread_mutex_unlock(&mutex_sum);

    pthread_exit((void *) thread_id);

}

输出

Resultant X*Y is 20900
time spent: 0.000155 NUM_THREADS: 2
Resultant X*Y is 19860
time spent: 0.000406 NUM_THREADS: 4
Resultant X*Y is 17680
time spent: 0.000112 NUM_THREADS: 8
Resultant X*Y is 5712
time spent: 0.000587 NUM_THREADS: 16