std :: thread ve std :: async arasında bir test kodu hazırladım. 4 çekirdekli CentOs 7 kutusu (gcc 4.8.5), Sürüm 1 ilestd :: thread std :: async, BÜYÜK performans kazancı sağlar. Nasıl mümkün olabilir?
#include <iostream>
#include <mutex>
#include <fstream>
#include <string>
#include <memory>
#include <thread>
#include <future>
#include <functional>
#include <boost/noncopyable.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/asio.hpp>
namespace fs = boost::filesystem;
namespace pt = boost::posix_time;
namespace as = boost::asio;
class Log : private boost::noncopyable
{
public:
void LogPath(const fs::path& filePath) {
boost::system::error_code ec;
if(fs::exists(filePath, ec)) {
fs::remove(filePath);
}
this->ofStreamPtr_.reset(new fs::ofstream(filePath));
};
void WriteLog(std::size_t i) {
assert(*this->ofStreamPtr_);
std::lock_guard<std::mutex> lock(this->logMutex_);
*this->ofStreamPtr_ << "Hello, World! " << i << "\n";
};
private:
std::mutex logMutex_;
std::unique_ptr<fs::ofstream> ofStreamPtr_;
};
int main(int argc, char *argv[]) {
if(argc != 2) {
std::cout << "Wrong argument" << std::endl;
exit(1);
}
std::size_t iter_count = boost::lexical_cast<std::size_t>(argv[1]);
Log log;
log.LogPath("log.txt");
std::function<void(std::size_t)> func = std::bind(&Log::WriteLog, &log, std::placeholders::_1);
auto start_time = pt::microsec_clock::local_time();
////// Version 1: use std::thread //////
// {
// std::vector<std::shared_ptr<std::thread> > threadList;
// threadList.reserve(iter_count);
// for(std::size_t i = 0; i < iter_count; i++) {
// threadList.push_back(
// std::make_shared<std::thread>(func, i));
// }
//
// for(auto it: threadList) {
// it->join();
// }
// }
// pt::time_duration duration = pt::microsec_clock::local_time() - start_time;
// std::cout << "Version 1: " << duration << std::endl;
////// Version 2: use std::async //////
start_time = pt::microsec_clock::local_time();
{
for(std::size_t i = 0; i < iter_count; i++) {
auto result = std::async(func, i);
}
}
duration = pt::microsec_clock::local_time() - start_time;
std::cout << "Version 2: " << duration << std::endl;
////// Version 3: use boost::asio::io_service //////
// start_time = pt::microsec_clock::local_time();
// {
// as::io_service ioService;
// as::io_service::strand strand{ioService};
// {
// for(std::size_t i = 0; i < iter_count; i++) {
// strand.post(std::bind(func, i));
// }
// }
// ioService.run();
// }
// duration = pt::microsec_clock::local_time() - start_time;
// std::cout << "Version 3: " << duration << std::endl;
}
yaklaşık 100 x yavaş diğer uygulamaları ile karşılaştırılır (STD :: iplik kullanılarak) dönüştürülmüştür.
Iteration Version1 Version2 Version3 100 0.0034s 0.000051s 0.000066s 1000 0.038s 0.00029s 0.00058s 10000 0.41s 0.0042s 0.0059s 100000 throw 0.026s 0.061s
Neden dişli sürüm çok yavaş? Her iş parçacığının Log::WriteLog
işlevini tamamlamak için uzun sürmeyeceğini düşündüm.
Benim görüşüme göre çok fazla iş parçacığı (cpu çekirdeklerinden daha fazlası) tetikliyorsunuz ve hepsi de cpu zamanı ve içerik geçişi için rekabet ediyorlar, yavaştır. Zaman uyumsuzluğu durumunda, çalışma zamanı kodunuzu yeterli sayıda iş parçacığı üzerinde etkin bir şekilde yönetir ve yürütür ve gerektiğinde işlemci zamanını verir. – Saleem
iş parçacığı _very_ genişliyor. çekirdek sayısından daha fazla bir şey, performansı düşürür (kilitlerle/IO tarafından engellenen konuları göz ardı eder). Bu yüzden iplik havuzu tavsiye edilir. –
Kodunuzun 100000 yinelemeyle başarısız olması, yeterince büyük bir ipucudur. Bir iş parçacığı, pahalı bir işletim sistemi nesnesidir ve bunları oluşturma ve bunları yeniden parçalama maliyetini ödersiniz. Eğer iş parçacığı tarafından yapılan iş miktarı bu kadar küçükse, o zaman kesinlikle yükü görürsünüz. Bir std :: async uygulaması bu maliyeti amorti edebilir, bir threadpool kullanarak standart bir tekniktir. Kaba bir kılavuz, bir iş parçacığının en az 100 mikrosaniye çalışması gerektiğidir, bir uyumsuzluk işlevi bir saniyeden fazla sürmemelidir. –