C++11æ¨æºä»¥éã®asyncã¨futureã«ããéåæå¦çã¯é常ã«ä½¿ãããããã¨ã¦ãç°¡åã«éåæå¦çãå®è£
ãããã¨ãã§ãããããã«ãã£ã¦ããã«ãã¹ã¬ããã§ã¯è¤æ°ã®å¦çã並åå®è¡ã§ããå ´åã«ã¯ãã¹ã«ã¼ããããåä¸ããããããä¸æ¹ã§ãåä¸ã®å¦çãã·ã³ã°ã«ã¹ã¬ããã§å¦çããå ´åã«ã¯ãã¹ã¬ãããä½ã£ããã¹ã¬ããéã®ã³ã³ããã¹ãã¹ã¤ããããããããã®ã«ããããªã¼ãã¼ãããã§ãã¹ã«ã¼ãããã¯ä½ä¸ãããããã«ã¤ãã¦æ§è½è©ä¾¡ããããã¹ã¬ãããã¼ã«ãå®è£
ãã¦ãããã¨ã®æ¯è¼ãè¡ã£ãã
å¤æ°ã100ä¸åã¤ã³ã¯ãªã¡ã³ãããã¨ããåç´ãªå¦çãèãããç¡çããã©ã ãå¼ã使ã£ã¦ãããåæå¼ã³åºãããããã«å®è£ ãããªãã以ä¸ã®ããã«ãªãã
TEST(ThreadUtilTest, TaskSimple) { constexpr int32_t num_tasks = 1000000; std::atomic_int32_t count = 0; for (int32_t i = 0; i < num_tasks; i++) { auto task = [&]() { count.fetch_add(1); }; task(); } EXPECT_EQ(num_tasks, count.load()); }
次ã«ãstd::asyncã®std::launch::deferredã¢ã¼ãã使ã£ãå®è£ ãèãããstd::asyncã¯ä»»æã®ã©ã ãå¼ã®é 延è©ä¾¡ãè¡ãä»çµã¿ã§ãstd::futureãªãã¸ã§ã¯ããè¿ãã¦ããããstd::launch::deferredã¢ã¼ããæå®ããå ´åãstd::futureã®wait/getã¡ã½ãããå¼ãã æã«è©ä¾¡ããããã¤ã¾ããé 延è©ä¾¡æã«åæçã«ã©ã ãå¼ãå®è¡ãããã®ã§ãå®éã«ã¯éåæå¦çã§ã¯ãªããããããå¾è¿°ã®éåæå¦çã¨å ¨ãåãã·ã³ã¿ãã¯ã¹ã§è¨è¿°ã§ããã®ãå©ç¹ã ã
TEST(ThreadUtilTest, TaskDeferred) { constexpr int32_t num_tasks = 1000000; std::atomic_int32_t count = 0; for (int32_t i = 0; i < num_tasks; i++) { auto task = [&]() { count.fetch_add(1); }; std::future<void> f = std::async(std::launch::deferred, task); f.wait(); } EXPECT_EQ(num_tasks, count.load()); }
ä¸è¿°ã®std::launch::deferredãstd::launch::asyncã«å¤ãã¦ããã¨ãçã®éåæå¦çãè¡ããããããã¯è£ã§ã¹ã¬ãããä½ããã¦ããã®ã¹ã¬ãããã©ã ãå¼ãå¦çããã®ã§ãstd::futureã®wait/getãå¼ã³åºãåã«å¥ã®å¦çãå ¥ãã¦ããã°ã並åå¦çãè¡ããããã¨ã«ãªãã
TEST(ThreadUtilTest, TaskAsync) { constexpr int32_t num_tasks = 1000000; std::atomic_int32_t count = 0; for (int32_t i = 0; i < num_tasks; i++) { auto task = [&]() { count.fetch_add(1); }; std::future<void> f = std::async(std::launch::async, task); f.wait(); } EXPECT_EQ(num_tasks, count.load()); }
std::asyncã¯ãæ軽ã§è¯ãã®ã ããæ¯åã¹ã¬ãããä½ãã®ã§ãå®è¡æã®ãªã¼ãã¼ãããã大ããããå«ãããããããã§ãã¹ã¬ãããã¼ã«ã使ã£ã¦ãäºã決ã¾ã£ãæ°ã§çæãã¦ãããã¹ã¬ããã使ãåãã®ã常å¥æ段ã ãã¹ã¬ãããã¼ã«ã¯ã¾ã æ¨æºåããã¦ããªãã®ã§ãç°¡åãªã¯ã©ã¹ãå®è£ ãã¦ããããコードはこちらã§ãããããã使ã£ããã¹ãã±ã¼ã¹ã¯ä»¥ä¸ã®ããã«ãªããä»åã¯1ã¹ã¬ããã®ã¿ã使ãã
TEST(ThreadUtilTest, TaskQueue) { constexpr int32_t num_tasks = 1000000; std::atomic_int32_t count = 0; tkrzw::TaskQueue queue; queue.Start(1); for (int32_t i = 0; i < num_tasks; i++) { auto task = [&]() { count.fetch_add(1); }; queue.Add(task); } queue.Stop(60); EXPECT_EQ(0, queue.GetSize()); EXPECT_EQ(num_tasks, count.load()); }
ä¸è¿°ã®ã¹ã¬ãããã¼ã«ã®ä¾ã ã¨ãã«ã¼ãå ã§ã¿ã¹ã¯ã®çµæãåãåã£ã¦ããªãã®ã§ãã»ãã³ãã£ã¯ã¹ãç°ãªããã¨ã«ãªãããããåãããã¹ããstd::promiseã¨std::futureã§åæãåãããã«ããã®ã以ä¸ã®ä¾ã§ããã
TEST(ThreadUtilTest, TaskQueueFuture) { constexpr int32_t num_tasks = 1000000; std::atomic_int32_t count = 0; tkrzw::TaskQueue queue; queue.Start(1); for (int32_t i = 0; i < num_tasks; i++) { std::promise<void> p; std::future<void> f = p.get_future(); auto task = [&]() { count.fetch_add(1); p.set_value(); }; queue.Add(task); f.wait(); } queue.Stop(0.05); EXPECT_EQ(0, queue.GetSize()); EXPECT_EQ(num_tasks, count.load()); }
ãªããstd::futureã使ããªãã¦ãstd::condition_variableã§åçã®å¦çãå®è£ ã§ããããã ãããã£ã¦ãããã¨ã¯std::futureã¨ã»ã¼åããªã®ã§ãå¹çã¯å¤ãããªããstd::futureã使ã£ãæ¹ãèªã¿ãããã®ã§ãç´æ¥std::condition_variableã使ãçç±ã¯ãªãã
TEST(ThreadUtilTest, TaskQueueCond) { constexpr int32_t num_tasks = 1000000; std::atomic_int32_t count = 0; tkrzw::TaskQueue queue; queue.Start(4); for (int32_t i = 0; i < num_tasks; i++) { std::mutex mutex; bool done = false; std::condition_variable cond; auto task = [&]() { count.fetch_add(1); { std::lock_guard<std::mutex> lock(mutex); done = true; } cond.notify_one(); }; queue.Add(task); std::unique_lock<std::mutex> lock(mutex); cond.wait(lock, [&]() { return done; }); } queue.Stop(0.05); EXPECT_EQ(0, queue.GetSize()); EXPECT_EQ(num_tasks, count.load()); }
çµæçºè¡¨ã100ä¸ãããã£ãæéã§å²ã£ã¦QPSï¼ç§éã¹ã«ã¼ãããï¼ãç®åºãããå®è¡ç°å¢ã¯Core i7 8550Uï¼8ã³ã¢ã1.8GHzï¼ä¸ã®Ubuntu 20.10ã§ãããã¹ã¬ãããã¼ã«ã¯ã¹ã¬ããã®æ°ã«ãã£ã¦ãªã¼ãã¼ããããå¤ããã®ã§ã1ã2ã4ã8ã16ã§å¥é測å®ããã
åæå¦ç | 1,428,571,428 QPS |
std::launch::deferred | 2,232,142 QPS |
std::launch::async | 59,988 QPS |
ã¹ã¬ãããã¼ã«1 | 2,415,458 QPS |
ã¹ã¬ãããã¼ã«2 | 1,371,742 QPS |
ã¹ã¬ãããã¼ã«4 | 375,093 QPS |
ã¹ã¬ãããã¼ã«8 | 434,782 QPS |
ã¹ã¬ãããã¼ã«16 | 457,875 QPS |
ã¹ã¬ãããã¼ã«1+future | 168,350 QPS |
ã¹ã¬ãããã¼ã«2+future | 150,285 QPS |
ã¹ã¬ãããã¼ã«4+future | 145,857 QPS |
ã¹ã¬ãããã¼ã«8+future | 145,011 QPS |
ã¹ã¬ãããã¼ã«16+future | 143,245 QPS |
ã¾ããåæå¦çã®çµæã¯ã足ãç®ããã¦ããã ãã«ãªãã®ã§ã14åQPSã¨ç°å¸¸ã«éããããã«æ¯ã¹ãã¨ãstd::launch::deferredã®é 延è©ä¾¡ãããã ãã§ã¹ã«ã¼ãããã¯223ä¸QPSã«ã¾ã§è½ã¡ã¦ãã¾ããããã¦ãstd::launch::asyncã®ã¹ã¬ããå¼ã³åºããããã¨ãã¹ã«ã¼ãããã¯6ä¸QPSã¾ã§è½ã¡ã¦ãã¾ããã¨ã¯ãããæ¯åã¹ã¬ãããçæãã¦ãã®ã¹ã«ã¼ããããåºãã®ã¯ãããªãæ©ãã¨ãè¨ãããããã§ãã¹ã¬ãããã¼ã«ã使ã£ãæ¹ãéãã«å¹çãè¯ãã1ã¹ã¬ãããªã241ä¸QPSã®ã¹ã«ã¼ããããåºããããã«ãªããããããã¹ã¬ãããã¼ã«ã使ã£ã¦ãã«ã¼ãå ã§åæããã¨ã¹ã«ã¼ãããã¯ã¬ã¯ãã¨è½ã¡ã¦ã16ä¸QPSã«ãªãã
ã¹ã¬ãããã¼ã«ã®ãªã¼ãã¼ãããã¯ã¹ã¬ããæ°ã«ãã£ã¦å¥å¦ãªå¤åãããã1ã¹ã¬ããã§241ä¸QPSãªã®ãã2ã¹ã¬ããã ã¨137ä¸QPSã«æªåããããã以éã¯ã4ã§37ä¸ã8ã§43ä¸ã16ã§45ä¸ã¨ãã¹ã¬ããæ°ã¨ã®ç¸é¢ãã»ã¨ãã©ãªããªããã¿ã¹ã¯ãã¥ã¼ã®è¿½å ãéç¥ããéã®æ¡ä»¶å¤æ°ã®æåãå¾éãã¦ãããããªæ°ã¯ãã¦ãããã確証ã¯ãªããä¸æ¹ãfutureã§åæããå ´åãã¹ã¬ããæ°ã«é¢ããã15ä¸QPSãããã®ã¹ã«ã¼ãããã«ãªãã
async+futureã®ã»ãã³ãã£ã¯ã¹ã¯ã¹ã¬ããã¼ãã¼ã«+futureãå®å ¨ã«ã«ãã¼ããã®ã§ãå¯è½ã§ããã°ã¹ã¬ãããã¼ã«ã使ãã¹ãã ãå ã ã®å¦çãããã¯ã°ã©ã¦ã³ãã§å®è¡ããã¨èããã¨ãããã¯ã°ã©ã¦ã³ãå¦çã¨ãã©ã¢ã°ã©ã¦ã³ãå¦çã®åæ¹ã6ä¸QPSãããé ããªãasync+futureã使ã£ã¦ãè¯ãããããããé«éãªå¦çã§ãã16ä¸QPSãããé ããªããã¹ã¬ãããã¼ã«+futureã使ã£ã¦è¯ããçæçãªå¾ ã¡åãããå¿ è¦ãªãã241ä¸QPSãããé ãå¦çãããã¯ã°ã©ã¦ã³ãã§åãããããªããã¹ã¬ãããã¼ã«ã«ãã®ãããªã¿ã¹ã¯ãå ¥ãã¦ããããããã§ãªããã°ãç´åã«ããæ¹ãããããã¡ã¤ã«I/Oããããã¯ã¼ã¯I/Oã絡ãå ´åã¯ä¸¦ååãã¹ãæ¡ä»¶ã®ã©ããã«å½ã¦ã¯ã¾ããã¨ãå¤ãã®ã§ããã¯ã並ååããæ¸ãæ¹ã¯ã¹ãã«ã»ããã¨ãã¦æã£ã¦ããã¹ãã ããã
ã¾ã¨ããasyncã¨futureã使ã£ãã¹ã¬ããçæãã¼ã¹ã®éåæå¦çã§ã¯ã6ä¸QPSãããåºãããå¹çãæé©ã¨ã¯ãããªãããã«ã¸ã¥ã¢ã«ãªã¦ã¼ã¹ã±ã¼ã¹ã¯ããã§ååã ãããã¨ã¯ãããã¹ã¬ãããã¼ã«ã使ãã°16ä¸QPSãããã¯241ä¸QPSã«æ¹åããã®ã§ãå¯è½ã§ããã°ã¹ã¬ãããã¼ã«ãæ´»ç¨ããæ¹ãè¯ãã
Tkrzwã®éåæAPIãå®è£ ãããã¨æã£ã¦ã¹ã¬ãããã¼ã«ã®å®è£ ãããã®ã ããC++ã§ã¯ã©ã ãå¼ã§ç°¡åã«éåæå¦çãæ¸ããã®ã§ããããããã¼ã¿ãã¼ã¹å´ã§éåæåã®é¢åãè¦ãå¿ è¦ã¯ãªãããã£ã¦ãã¹ã¬ãããã¼ã«ãã®ãã®ãã©ã¤ãã©ãªã®ã¦ã¼ãã£ãªãã£ã«å«ãã¦ãå¿ è¦ã§ããã°ä½¿ã£ã¦ãã¨ããæãã«ãã¦æ¸ã¾ãããã¨æãããã ãPythonãRubyã®APIãèããã¨ãåå¦çç³»ã®ã¹ã¬ããæ©æ§ãã³ã«ã¼ãã³ã®ãªã¼ãã¼ããããåé¿ãã¤ã¤ããã¤ãã£ãã¹ã¬ããã§ã®ä¸¦åå¦çãã§ããã®ã§ããã¯ãéåæAPIãå®è£ ãã¦ãããããªã¨ããæ°ã«ããªããæ©ã¾ããã¨ããã ã