最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言中的rand()和rand_r()詳解

 更新時(shí)間:2021年12月19日 16:48:06   作者:高階近似  
這篇文章主要為大家介紹了C語(yǔ)言中的rand()和rand_r(),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

背景

最近在學(xué)《并行程序設(shè)計(jì)導(dǎo)論》這門(mén)課,在做使用Pthreads并行化蒙特卡洛法估計(jì) π \pi π的實(shí)驗(yàn)時(shí)遇到了一個(gè)問(wèn)題,使用多線程反而要比單線程要慢很多,輸出如下所示

請(qǐng)?zhí)砑訄D片描述

可以看到,使用一個(gè)線程時(shí)程序運(yùn)行只需要2.89031秒,但是使用兩個(gè)線程時(shí)運(yùn)行時(shí)間竟然達(dá)到了9.14698秒。

最終發(fā)現(xiàn)了問(wèn)題所在:每個(gè)線程在執(zhí)行下面的函數(shù)時(shí),生成隨機(jī)數(shù)使用了rand()函數(shù),就是這個(gè)函數(shù)的使用才導(dǎo)致多線程運(yùn)行時(shí)所需要的時(shí)間反而更長(zhǎng)

long long total_times_in_cycle;
long long local_number_toss;
pthread_mutex_t times_in_cycle_mutex = PTHREAD_MUTEX_INITIALIZER;
void* do_Monte_Carlo_simulation(void* my_rank){
	double offset = RAND_MAX / (double)2;
    long long times_in_cycle = 0;
    long long i;
    for(i = 0; i < local_number_toss; ++i){
        double x = rand() / offset - 1;
        double y = rand() / offset - 1;
        if(x*x + y*y < 1){
            times_in_cycle++;
        }
    }
    pthread_mutex_lock(&times_in_cycle_mutex);
    total_times_in_cycle += times_in_cycle;
    pthread_mutex_unlock(&times_in_cycle_mutex);
}

rand()和rand_r()的區(qū)別

權(quán)威的解釋請(qǐng)參考Linux的官方文檔
這里主要說(shuō)說(shuō)我個(gè)人的理解。

rand()

對(duì)于rand():

srand()和rand()配套一起使用,可以認(rèn)為是進(jìn)程只生成了一個(gè)隨機(jī)數(shù)生成器,所有的線程共用這個(gè)隨機(jī)數(shù)生成器。每調(diào)用一次rand(),rand()都會(huì)去修改這個(gè)隨機(jī)數(shù)生成器的一些參數(shù),比如說(shuō)當(dāng)前種子的值。對(duì)于單線程,這樣是沒(méi)有問(wèn)題的,但是對(duì)于多線程而言,這顯然會(huì)導(dǎo)致臨界段問(wèn)題,為了解決該問(wèn)題,可能會(huì)使用互斥量等方法,下面假設(shè)多個(gè)線程同時(shí)使用rand()的時(shí)候使用互斥量來(lái)解決該臨界段問(wèn)題。如果rand()調(diào)用的次數(shù)不多,多線程也問(wèn)題不大,但是對(duì)于上述蒙特卡洛法估計(jì) π \pi π的程序,需要調(diào)用很多次rand(),這可能會(huì)導(dǎo)致每個(gè)線程頻繁地對(duì)臨界段進(jìn)行上鎖和解鎖,而臨界段被上鎖后,其他線程無(wú)法完成rand()的調(diào)用從而被阻塞,這樣會(huì)導(dǎo)致效率十分低下,因此會(huì)出現(xiàn)使用多線程反而程序運(yùn)行更慢的問(wèn)題。

srand()和rand()配套一起使用,可以認(rèn)為是進(jìn)程只生成了一個(gè)隨機(jī)數(shù)生成器,所有的線程共用這個(gè)隨機(jī)數(shù)生成器?這點(diǎn)可以用下面的程序進(jìn)行驗(yàn)證,該程序從命令行獲取要生成隨機(jī)數(shù)的數(shù)量以及線程的數(shù)量,每個(gè)線程負(fù)責(zé)生成?隨機(jī)數(shù)的數(shù)量/線程的數(shù)量?個(gè)隨機(jī)數(shù),隨機(jī)數(shù)種子設(shè)為0.

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

int generate_rand_count;
int thread_count;

// 被線程執(zhí)行的函數(shù)
void* thread_func(void* my_rank){
    int i;
    int local_rand_count = generate_rand_count / thread_count;
    for(i = 0; i < local_rand_count; ++i){
        printf("%d ", rand());
    }
}

int main(int argc, char* argv[]){
    pthread_t* all_threads_id;

    // 從命令行獲取要生成的隨機(jī)數(shù)的數(shù)量以及這些隨機(jī)數(shù)由多少個(gè)線程來(lái)生成
    generate_rand_count = strtol(argv[1], NULL, 10);
    thread_count = strtol(argv[2], NULL, 10);
    all_threads_id = malloc(sizeof(pthread_t) * thread_count);

    // 設(shè)置隨機(jī)數(shù)種子
    srand(0);

    // 創(chuàng)建線程
    int i;
    for(i = 0; i < thread_count; ++i){
        pthread_create(&all_threads_id[i], NULL, thread_func, (void*) i);
    }

    for(i = 0; i < thread_count; ++i){
        pthread_join(all_threads_id[i], NULL);
    }
    
    printf("\n");
    free(all_threads_id);
    return 0;
}

執(zhí)行結(jié)果如下所示

請(qǐng)?zhí)砑訄D片描述

可以看到,無(wú)論使用一個(gè)線程生成10個(gè)隨機(jī)數(shù),還是說(shuō)使用兩個(gè)線程來(lái)生成10個(gè)隨機(jī)數(shù),它們生成的這10個(gè)隨機(jī)數(shù)是一樣的,這也就驗(yàn)證了?所有的線程共用一個(gè)隨機(jī)數(shù)生成器?的觀點(diǎn)

rand_r()

rand_r()的聲明如下所示

int rand_r(unsigned int *seedp);

每次使用rand_r()的時(shí)候需要傳給該函數(shù)一個(gè)隨機(jī)數(shù)種子的指針,為了解決蒙特卡洛方法估計(jì) π \pi π中出現(xiàn)的問(wèn)題,使用如下的代碼:

long long total_times_in_cycle;
long long local_number_toss;
pthread_mutex_t times_in_cycle_mutex = PTHREAD_MUTEX_INITIALIZER;
void* do_Monte_Carlo_simulation(void* my_rank){
	unsigned int local_seed = time(NULL);
	double offset = RAND_MAX / (double)2;
    long long times_in_cycle = 0;
    long long i;
    for(i = 0; i < local_number_toss; ++i){
        double x = rand_r(&local_seed) / offset - 1;
        double y = rand_r(&local_seed) / offset - 1;
        if(x*x + y*y < 1){
            times_in_cycle++;
        }
    }
    pthread_mutex_lock(&times_in_cycle_mutex);
    total_times_in_cycle += times_in_cycle;
    pthread_mutex_unlock(&times_in_cycle_mutex);
}

每個(gè)線程執(zhí)行函數(shù)do_Monte_Carlo_simulation()。

使用上面的代碼后,相當(dāng)于每個(gè)線程生成了它自己獨(dú)有的隨機(jī)數(shù)生成器,這樣就不會(huì)有臨界段問(wèn)題,從而解決了多線程運(yùn)行時(shí)所需要的時(shí)間反而更長(zhǎng)這個(gè)問(wèn)題,下面為更改后程序的輸出:

請(qǐng)?zhí)砑訄D片描述

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • C++線程之thread詳解

    C++線程之thread詳解

    這篇文章主要為大家詳細(xì)介紹了C++線程中的thread,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • 深入探討Linux靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的詳解(一看就懂)

    深入探討Linux靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的詳解(一看就懂)

    本篇文章是對(duì)Linux靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++中關(guān)于Crt的內(nèi)存泄漏檢測(cè)的分析介紹

    C++中關(guān)于Crt的內(nèi)存泄漏檢測(cè)的分析介紹

    本篇文章介紹了,在C++中關(guān)于Crt的內(nèi)存泄漏檢測(cè)的分析說(shuō)明。需要的朋友參考下
    2013-04-04
  • C++?pthread入門(mén)指南

    C++?pthread入門(mén)指南

    pthread是C++98接口且只支持Linux,使用時(shí)需要包含頭文件#include?<pthread.h>,編譯時(shí)需要鏈接pthread庫(kù),其中p是POSIX的縮寫(xiě),而POSIX是Portable?Operating?System?Interface的縮寫(xiě),這篇文章主要介紹了C++?pthread簡(jiǎn)介,需要的朋友可以參考下
    2024-05-05
  • C++ Boost.Range與Adapters庫(kù)使用詳解

    C++ Boost.Range與Adapters庫(kù)使用詳解

    這篇文章主要介紹了C++ Boost.Range與Adapters庫(kù)使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-11-11
  • C語(yǔ)言使用深度優(yōu)先搜索算法解決迷宮問(wèn)題(堆棧)

    C語(yǔ)言使用深度優(yōu)先搜索算法解決迷宮問(wèn)題(堆棧)

    這篇文章主要介紹了C語(yǔ)言使用深度優(yōu)先搜索算法解決迷宮問(wèn)題,涉及C語(yǔ)言堆棧的使用與深度優(yōu)先算法解決迷宮問(wèn)題的相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • 常用C/C++預(yù)處理指令詳解

    常用C/C++預(yù)處理指令詳解

    預(yù)處理指令提供按條件跳過(guò)源文件中的節(jié)、報(bào)告錯(cuò)誤和警告條件,以及描繪源代碼的不同區(qū)域的能力。使用術(shù)語(yǔ)“預(yù)處理指令”只是為了與 C 和 C++ 編程語(yǔ)言保持一致。在 C# 中沒(méi)有單獨(dú)的預(yù)處理步驟;預(yù)處理指令按詞法分析階段的一部分處理。
    2014-11-11
  • C++實(shí)現(xiàn)批量圖片拼接

    C++實(shí)現(xiàn)批量圖片拼接

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)批量圖片拼接,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C++如何動(dòng)態(tài)的生成對(duì)象詳解

    C++如何動(dòng)態(tài)的生成對(duì)象詳解

    C++是不支持根據(jù)類(lèi)名動(dòng)態(tài)地生成對(duì)象的,比如從一個(gè)文本文件中讀取類(lèi)名然后構(gòu)造一個(gè)對(duì)象.主要原因是沒(méi)有豐富的動(dòng)態(tài)元信息,沒(méi)有單根類(lèi)庫(kù)。那么下面這篇文章就來(lái)給大家介紹C++是如何動(dòng)態(tài)的生成對(duì)象,有需要的朋友們可以參考借鑒。
    2017-02-02
  • 詳解c語(yǔ)言中的 strcpy和strncpy字符串函數(shù)使用

    詳解c語(yǔ)言中的 strcpy和strncpy字符串函數(shù)使用

    strcpy 和strcnpy函數(shù)是字符串復(fù)制函數(shù)。接下來(lái)通過(guò)本文給大家介紹c語(yǔ)言中的strcpy和strncpy字符串函數(shù)使用,感興趣的朋友跟隨小編要求看看吧
    2018-10-10

最新評(píng)論

黄梅县| 定陶县| 永宁县| 洛宁县| 张家界市| 石家庄市| 祁门县| 江源县| 怀安县| 年辖:市辖区| 汝城县| 尚义县| 肇庆市| 石台县| 南召县| 仲巴县| 广丰县| 亚东县| 同仁县| 汝南县| 北碚区| 小金县| 昔阳县| 专栏| 固镇县| 嘉定区| 南康市| 西昌市| 罗城| 芜湖县| 伊吾县| 望谟县| 温泉县| 灌阳县| 高安市| 武威市| 宜君县| 临沧市| 贵阳市| 仙居县| 六枝特区|