第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會有你想問的

go 和 c++ 之間的地圖性能比較

go 和 c++ 之間的地圖性能比較

Go
POPMUISE 2023-06-05 18:29:52
我不明白golang怎么在這個(gè)操作上比c++快10倍,甚至go中的map查找比c++快3倍。這是 C++ 片段#include <iostream>#include <unordered_map>#include <chrono>std::chrono::nanoseconds elapsed(std::chrono::steady_clock::time_point start) {    std::chrono::steady_clock::time_point now = std::chrono::high_resolution_clock::now();    return std::chrono::duration_cast<std::chrono::nanoseconds>(now - start);}void make_map(int times) {    std::unordered_map<double, double> hm;    double c = 0.0;    for (int i = 0; i < times; i++) {        hm[c] = c + 10.0;        c += 1.0;    }}int main() {    std::chrono::steady_clock::time_point start_time = std::chrono::high_resolution_clock::now();    make_map(10000000);    printf("elapsed %lld", elapsed(start_time).count());}這是 golang 片段:func makeMap() {    o := make(map[float64]float64)    var i float64 = 0    x := time.Now()    for ; i <= 10000000; i++ {        o[i] = i+ 10    }    TimeTrack(x)}func TimeTrack(start time.Time) {    elapsed := time.Since(start)    // Skip this function, and fetch the PC and file for its parent.    pc, _, _, _ := runtime.Caller(1)    // Retrieve a function object this functions parent.    funcObj := runtime.FuncForPC(pc)    // Regex to extract just the function name (and not the module path).    runtimeFunc := regexp.MustCompile(`^.*\.(.*)$`)    name := runtimeFunc.ReplaceAllString(funcObj.Name(), "$1")    log.Println(fmt.Sprintf("%s took %s", name, elapsed))}我想知道的是如何優(yōu)化 c++ 以獲得更好的性能。
查看完整描述

3 回答

?
蝴蝶不菲

TA貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超4個(gè)贊

很難確定“C++ 的速度”(對于幾乎任何特定事物),因?yàn)樗赡苋Q于相當(dāng)多的變量,例如您使用的編譯器。例如,對于此代碼的 C++ 版本,我通常會看到 gcc 和 msvc 之間存在 2:1 左右的差異。

至于 C++ 和 Go 之間的差異,我猜這主要?dú)w結(jié)于哈希表的實(shí)現(xiàn)方式的差異。一個(gè)明顯的一點(diǎn)是 Go 的 map 實(shí)現(xiàn)一次以 8 個(gè)元素的塊為單位分配數(shù)據(jù)空間。至少我見過的標(biāo)準(zhǔn)庫實(shí)現(xiàn),std::unordered_map每個(gè)塊只放置一個(gè)項(xiàng)目。

我們希望這意味著在典型情況下,C++ 代碼將從堆/空閑存儲中進(jìn)行大量的單獨(dú)分配,因此它的速度將更多地取決于堆管理器的速度。Go 版本還應(yīng)該具有更高的引用位置,以便更好地使用緩存。

考慮到這些差異,我有點(diǎn)驚訝您只看到 10:1 的差異。我的直接猜測會(稍微)高于這個(gè)數(shù)值——但眾所周知,一次測量值超過 100 次猜測。


查看完整回答
反對 回復(fù) 2023-06-05
?
繁花不似錦

TA貢獻(xiàn)1851條經(jīng)驗(yàn) 獲得超4個(gè)贊

已更新以測量cpp和的類似操作go。它在調(diào)用制圖函數(shù)之前開始測量,并在函數(shù)返回時(shí)結(jié)束測量。兩個(gè)版本都在地圖中保留空間并返回創(chuàng)建的地圖(從中打印了幾個(gè)數(shù)字)。


稍作修改cpp:


#include <iostream>

#include <unordered_map>

#include <chrono>


std::unordered_map<double, double> make_map(double times) {

    std::unordered_map<double, double> m(times);


    for (double c = 0; c < times; ++c) {

        m[c] = c + 10.0;

    }

    return m;

}


int main() {

    std::chrono::high_resolution_clock::time_point start_time = std::chrono::high_resolution_clock::now();

    auto m = make_map(10000000);

    std::chrono::high_resolution_clock::time_point end_time = std::chrono::high_resolution_clock::now();

    auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time-start_time);

    std::cout << elapsed.count()/1000000000. << "s\n";

    std::cout << m[10] << "\n"

              << m[9999999] << "\n";    

}


% g++ -DNDEBUG -std=c++17 -Ofast -o perf perf.cpp

% ./perf

2.81886s

20

1e+07

稍作修改的go版本:


package main


import (

    "fmt"

    "time"

)


func make_map(elem float64) map[float64]float64 {

    m := make(map[float64]float64, int(elem))

    var i float64 = 0

    for ; i < elem; i++ {

        m[i] = i + 10

    }

    return m

}


func main() {

    start_time := time.Now()

    r := make_map(10000000)

    end_time := time.Now()

    fmt.Println(end_time.Sub(start_time))

    fmt.Println(r[10])

    fmt.Println(r[9999999])

}


% go build -a perf.go

% ./perf

1.967707381s

20

1.0000009e+07

它看起來不像更新前那樣平局。使 cpp 版本變慢的一件事是double. 當(dāng)用一個(gè)非常糟糕(但很快)的哈希器替換它時(shí),我把時(shí)間降到了 1.89489s。


struct bad_hasher {

    size_t operator()(const double& d) const {

        static_assert(sizeof(double)==sizeof(size_t));


        return

            *reinterpret_cast<const size_t*>( reinterpret_cast<const std::byte*>(&d) );

    }

};


查看完整回答
反對 回復(fù) 2023-06-05
?
大話西游666

TA貢獻(xiàn)1817條經(jīng)驗(yàn) 獲得超14個(gè)贊

無意義的微基準(zhǔn)測試產(chǎn)生無意義的結(jié)果。


繼續(xù)@mrclx和@TedLyngmo的微基準(zhǔn)線程,修復(fù)@TedLyngmo 的 Go 微基準(zhǔn)中的錯(cuò)誤:

perf.go:

package main


import (

? ? "fmt"

? ? "time"

)


func makeMap(elem float64) time.Duration {

? ? x := time.Now()

? ? o := make(map[float64]float64, int(elem))

? ? var i float64 = 0

? ? for ; i < elem; i++ {

? ? ? ? o[i] = i + 10

? ? }

? ? t := time.Now()

? ? return t.Sub(x)

}


func main() {

? ? r := makeMap(10000000)

? ? fmt.Println(r)

}

輸出:


$ go version

go version devel +11af353531 Tue Feb 12 14:48:26 2019 +0000 linux/amd64

$ go build -a perf.go

$ ./perf

1.649880112s

$?

perf.cpp:


#include <iostream>

#include <unordered_map>

#include <chrono>


void make_map(double times) {

? ? std::unordered_map<double, double> hm;

? ? hm.reserve(static_cast<size_t>(times)); // <- good stuff


? ? for (double c = 0; c < times; ++c) {

? ? ? ? hm[c] = c + 10.0;

? ? }

}


int main() {

? ? std::chrono::high_resolution_clock::time_point start_time = std::chrono::high_resolution_clock::now();

? ? make_map(10000000);

? ? std::chrono::high_resolution_clock::time_point end_time = std::chrono::high_resolution_clock::now();

? ? auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time-start_time);

? ? std::cout << elapsed.count()/1000000000. << "s\n";

}

輸出:


$ g++ --version

g++ (Ubuntu 8.2.0-7ubuntu1) 8.2.0

$ g++ -DNDEBUG -std=c++17 -Ofast -o perf perf.cpp

$ ./perf

3.09203s

$?


查看完整回答
反對 回復(fù) 2023-06-05
  • 3 回答
  • 0 關(guān)注
  • 314 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號