並列計算の高次元ベクトル - マルチスレッドのpthreadを得ます

はじめのpthread

実際にはpthreadのは、C / C ++のライブラリとして扱われ、すべての機能とデータ型は、<pthread.hの>です。あなたはpthreadのを使用している場合AVXと同じように、あなたはパラメータを追加する必要があり、コンパイル時にコンパイル-lpthread。使用GCCコンパイラディレクティブは、次のとおりです。

gcc filename.c -lpthread

pthreadのエントリー

pthreadのCプログラムは、実行時にプロセスが複数の実行スレッドに分岐することができるようにすることです。主な機能は、例えば、次の2つのスレッドに分岐することができます。

[外国チェーンの写真は、ソースステーションは、セキュリティチェーン機構を有していてもよい失敗ダンプ、ダウン直接アップロードした画像を保存することをお勧めします(IMG-H5h5v5dp-1583848666993)(C:\ Users \ユーザーyangxr \のAppData \ローミング\ Typora \ typora-ユーザー画像\画像20200310194350428.png)]

分岐部、操作、合併:pthreadのは3つの部分に分かれている、と考えるのは簡単です。プログラム内のすべてのプロセスは以下の通りです。

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

int thread_count = 4;
void *Hello(void *rank);

int main()
{
    // 循环变量
    long thread;
    // 进程的标号,数组
    pthread_t *thread_handles;
    // 分配空间
    thread_handles =(pthread_t *)malloc(thread_count * sizeof(pthread_t));

    // 绑定线程,开始分叉
    for (thread = 0; thread < thread_count; ++thread)
    // 将线程hello,和给hello的参数绑定到线程上
    // thread就是循环变量传递给每一个线程中执行的函数
        pthread_create(&thread_handles[thread], NULL,
        Hello, (void *)thread);
    
    printf("Hello from the main thread\n");
    // 结束线程
    for (thread = 0; thread < thread_count; ++thread)
        pthread_join(thread_handles[thread], NULL);

    free(thread_handles);    
    return 0;
}

void *Hello(void *rank)
{
    long my_rank = (long)rank;
    printf("Hello from thread %ld of %d\n", my_rank, thread_count);
    return NULL;
}

pthread_createの機能の発散を使用してください。最初のパラメータは、その上にNULLに、低い第2パラメータよりある、スレッドpthread_createの符号の関数であり、3番目のパラメータはNULLポインタを送信する、NULLポインタは、署名機能、実行のスレッドの関数を返す必要がありますパラメータの第4パラメータ送信パラメータは、また、ヌルポインタに転送されなければなりません。

動作中のスレッドは、こんにちはに4つのプロセスを実行しています

使用pthread_joinを合併、糸の終わり。最初のパラメータは、スレッドpthread_joinを指数であり、第2のパラメータはNULLに、ではないという。

マルチスレッドコンピューティング高次元ベクトル加算

目的

テスト計算 1 0 7 10 ^ 7 ループ通常のAVXの速度差加算器を使用して、次元ベクトル

実験テストデータ型倍精度浮動小数点型ダブル、二つのベクトル 1 0 7 10 ^ 7 種類のダブルデータ。

さらに騒ぎがなければ、コードに。

コード

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
// 定义向量的长度
#define __VEC_LENGTH__ 10000000

// 线程数量
int thread_count = 4;
// 第一个向量
double arr1[__VEC_LENGTH__];
// 第二个向量
double arr2[__VEC_LENGTH__];
// 计算加法的结果
double result[__VEC_LENGTH__];
// 每个线程执行的函数
void *sum_vec(void *rank);

int main()
{
    long thread;
    pthread_t *thread_handles;
    int i;
    srand(time(NULL));
    thread_handles =(pthread_t *)malloc(thread_count * sizeof(pthread_t));
    for(i = 0; i < __VEC_LENGTH__; ++i)//随机初始化函数
    {
        arr1[i] = rand() / 9999;
        arr2[i] = rand() / 9999;
    }

    struct timeval tv1, tv2;
    gettimeofday(&tv1, NULL);
    // 绑定线程,开始分叉
    for (thread = 0; thread < thread_count; ++thread)
    // 将线程hello,和给hello的参数绑定到线程上
        pthread_create(&thread_handles[thread], NULL,
        sum_vec, (void *)thread);

    // 结束线程
    for (thread = 0; thread < thread_count; ++thread)
        pthread_join(thread_handles[thread], NULL);
    gettimeofday(&tv2, NULL);
    // 输出高维加法执行时间
    printf("Spliting the date to 4 pieces takes %ld us\n",
        (tv2.tv_usec - tv1.tv_usec));
    
    printf("The first three elements of result is %lf %lf %lf\n",
        result[0], result[1], result[2]);
    free(thread_handles);    
    return 0;
}

これらは、特定の機能を追加する下部に、点ではなく、主な機能および実行の各スレッドの関数シグネチャです。通常の配列は、あまりにも単純な足し算を達成するために、あなたはを参照することができ、この記事このコード

void *sum_vec(void *rank)
{
    long my_rank = (long)rank;

    // 每个线程都计算 __VEC_LENGTH__ / thread_count 个元素相加
    int i;
    int my_work = __VEC_LENGTH__ / thread_count;
    int my_first = my_rank * my_work;
    int my_last = (my_rank + 1) * my_work;

    for (i = my_first; i < my_last; ++i)
    {
        result[i] = arr1[i] + arr2[i];
    }
    return NULL;
}

業績

1 2 3 4 5 手段
マルチスレッド追加(単位UM) 50001 36446 40988 49006 47004 44689.0
(UM)でスレッド化に加え 112990 143994 138008 93993 90017 115800.4

実験的なテストケース5つの4スレッドは2.59の比を加速しました。

注:Ryzen 5 3500U上のプログラムの実行

話し合います

(1)マルチスレッド・プログラムの実行時間は、このように図を与え、低減されたスレッドの増加には不可能であった場合に11件のスレッド(単位はUMである)の実行時間スレッド:

(2)計算ベクトル加算を平行に二つの異なる方法を使用して、スレッドの理論的な数は、(アムダールの法則に従う)4最大のスピードアップは、4であるべきです。しかし、実際の動作中に、オーバーヘッド機能がマルチスレッドされているので、など、メモリを割り当てるために呼び出され、これまで高速化4に到達しませんでした。もちろん、コンパイル時があるかもしれない、コンパイラが最適化される元のコードに平行でない、ループは、加速度比を生じる、並列実行のために簡単になるが4未満です。

リリース3元の記事 ウォンの賞賛0 ビュー90

おすすめ

転載: blog.csdn.net/weixin_43252268/article/details/104784554