【问题标题】:Measuring speed up of a multi threaded C program (implementation using Pthreads)测量多线程 C 程序的加速(使用 Pthreads 实现)
【发布时间】:2017-01-01 12:42:02
【问题描述】:

我目前有一个使用 Pthreads 编码的多线程 C 程序,它使用 2 个线程。我想增加编号。线程和测量速度这样做。我想以自动化方式运行我的代码,其中没有。使用的线程数不断增加,我想以图形方式显示我的代码的运行时间。如果我能知道如何做到这一点,尤其是如何自动化整个过程并以图形方式绘制它,我会很高兴的。这是我的代码:

#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 参数并在每次增加后运行它,记录每次增加后的执行时间并绘制执行时间与线程数的关系图。

【问题讨论】:

  • 哪个操作系统?为了明确一点,您是否已经设法让您的应用程序使用任意数量的线程,或者您也在为此寻求帮助?
  • 我编写了我的代码,它使用 n 个线程,尽管在整个执行周期中是一个常数。我的操作系统是 macOS Sierra。
  • 我可以改变我的 NUM_THREADS 参数并单独运行它,但我想自动化该过程,记录每个循环的执行时间并以图形方式显示。
  • 您可以修改代码以从命令行或标准输入中获取线程数。然后你可以编写一个脚本来多次调用你的程序。我不精通Mac,但我认为你可以使用Bash 和time 来衡量你的程序。
  • 或者不修改程序,更简单的解决方案是让您的脚本将NUM_THREADS 作为宏提供给编译器。在 GCC 中,您可以为此使用选项 -D。编写一个脚本,用不同数量的线程编译你的程序,运行它,并测量运行时间。

标签: c multithreading pthreads


【解决方案1】:

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

#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

【讨论】:

    猜你喜欢
    • 2012-07-05
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多