ã5æã®æ«ãVisual Studio 2012 RCããªãªã¼ã¹ããã¾ãããåã¯æ ¹ã£ããã®C++å±ã§ããããèå³ã®å¯¾è±¡ã¯ç¬¬ä¸ã«Visual C++ 2012ï¼ä»¥ä¸ãVC11ï¼ã§ããç¾Visual C++ 2010ï¼VC10ï¼ã«ã¯lambdaãªã©ã®å½éæ¨æºC++11ã®ä¸é¨ããµãã¼ããã¦ãã¾ããã©ãVC11ã§ã¯ããã«C++ã®ãµãã¼ãç¯å²ãåºãã£ã¦ãã¾ããä»åã¯VC++11ã§æ°ãã«è¿½å ãããæ¨æºã¹ã¬ããã»ã©ã¤ãã©ãªã®ãç´¹ä»ã§ãã
åä¸æªæºã®ç´ æ°ã¯ããã¤ããï¼
ãã1ã¨ããèªèº«ä»¥å¤ã®ç´æ°ãæããªãæ°ããç´ æ°ã§ããè¨ãæããã°ã2以ä¸næªæºã®ãã¹ã¦ã®æ°ã§nãå²ãåããã¨ãã§ããªããã°ãnã¯ç´ æ°ãã§ããããã ããnãç´ æ°ã§ãããå¦ããå¤å®ããé¢æ°ã¯ãããªã«ã³ã¸ã
// nã¯ç´ æ°? bool is_prime(int n) { for ( int i = 2; i < n; ++i ) { if ( n % i == 0 ) { return false; } } return true; }
ããã®is_primeã使ã£ã¦ãlo以ä¸hiæªæºã®ç¯å²ã«ããç´ æ°ã®æ°ããæ±ããé¢æ°count_primeã¯
// lo以ä¸hiæªæºã®ç¯å²ã«ç´ æ°ã¯ããã¤ãã? int count_prime(int lo, int_hi) { int result = 0; for ( int i = lo; i < hi; ++i ) { if ( is_prime(i) ) { ++result; } } return result; }
ã10ä¸æªæºã®ç´ æ°ãåå®ãã¦ã¿ã¾ãããã
/* * Mæªæºã®ç´ æ°ã¯ããã¤ãã? */ void single(int M) { chrono::system_clock::time_point start = chrono::system_clock::now(); int result = count_prime(2,M); chrono::duration<double> sec = chrono::system_clock::now() - start; cout << result << ' ' << sec.count() << "[sec]" << endl; } int main() { const int M = 100000; single(M); } /* å®è¡çµæ: 9592 1.64009[sec] */
ã10ä¸ã¾ã§ã®æ´æ°ã«ã¯ï¼å²å¼±ã®ç´ æ°ããããã§ããããåã®ãã·ã³ï¼i7-2600KãWindows7-64bitï¼ã§ã¯1.6ç§ã»ã©ã§çããåºãã¦ããã¾ããã
0ï¼Windows API
ããã®è¨ç®ããã«ãã¹ã¬ããã«ããé«éåã試ã¿ã¾ããæ¦ç¥ã¯ããã£ã¦åç´ãç´ æ°ãå¦ãã®å¤å®ç¯å²ã[2,M) (2以ä¸Mæªæº,M=100000)ãã¹ã¬ããæ°ã§çåãã¾ãããã¨ãã°ã¹ã¬ãããµãã¤ãªã [2,M/2) 㨠[M/2,M)ã«ããã§ãã£ã¦åã¹ã¬ããã«åå²ãããç¯å²ã§ã®ç´ æ°ã®åå®ãåæ ãããããããã®çµæãå ¨é¨è¶³ãåãããã°ãããããã¨ã
ãã¾ãã¯Windows APIã§å®è£ ãã¾ããç¯å²[lo,hi)ãnçåããã¯ã©ã¹div_rangeãç¨æãã¾ãã
#ifndef DIV_RANGE_H_ #define DIV_RANGE_H_ // [lo,hi) ã nçåãã template<typename T =int> class div_range { private: T lo_; T hi_; T stride_; int n_; public: div_range(T lo, T hi, int n) : lo_(lo), hi_(hi), n_(n) { stride_ = (hi-lo)/n; } T lo(int n) const { return lo_ + stride_ * n; } T hi(int n) const { return (++n < n_) ? lo_ + stride_*n : hi_; } }; #endif
ãåå²ãããç¯å²ãã¨ã«ã¹ã¬ãããèµ·ãããå ¨ã¹ã¬ãããå®äºããã¨ããã§ç©ç®ãã¾ãã
/* Win32 thread ã®ããã®wrapper */ // <0>:loi, <1>:hi , <1>:result typedef tuple<int,int,int> thread_io; DWORD WINAPI thread_entry(LPVOID argv) { thread_io& io = *static_cast<thread_io*>(argv); get<2>(io) = count_prime(get<0>(io), get<1>(io)); return 0; } /* * Mæªæºã®ç´ æ°ã¯ããã¤ãã? */ void multi(int M, int nthr) { vector<HANDLE> handle(nthr); vector<thread_io> io(nthr); div_range<> rng(2,M,nthr); for ( int i = 0; i< nthr; ++i ) { io[i] = thread_io(rng.lo(i), rng.hi(i), 0); } chrono::system_clock::time_point start = chrono::system_clock::now(); for ( int i = 0; i< nthr; ++i ) { handle[i] = CreateThread(NULL, 0, &thread_entry, &io[i], 0, NULL); } WaitForMultipleObjects(nthr, &handle[0], TRUE, INFINITE); chrono::duration<double> sec = chrono::system_clock::now() - start; int result = 0; for ( int i = 0; i < nthr; ++i ) { CloseHandle(handle[i]); result += get<2>(io[i]); } cout << result << ' ' << sec.count() << "[sec] : " << nthr << endl; } int main() { const int M = 100000; for ( int i = 1; i < 10; ++i ) multi(M, i); } /* å®è¡çµæ: 9592 1.6651[sec] : 1 9592 1.21607[sec] : 2 9592 0.970055[sec] : 3 9592 0.752043[sec] : 4 9592 0.631036[sec] : 5 9592 0.52903[sec] : 6 9592 0.549031[sec] : 7 9592 0.497028[sec] : 8 9592 0.470027[sec] : 9 */
ãã¹ã¬ããæ°1ï½9ã§å®è¡ããã¨ã8åã®è«çã³ã¢ãæã¤i7ã§ã¯å½ç¶ã®ãã¨ãªããã¹ã¬ãã8åãããã§ã¹ãã¼ãé æã¡ã¨ãªãã¾ãã3åã¡ãã£ã¨éããªã£ã¦ã¾ãããWindow-APIã§å®è£ ããå ´åãã¹ã¬ããã®æ¬ä½ã§ããcount_primeãã¹ã¬ããã«ä¹ã£ããããã®wrapperï¼ãã®ãµã³ãã«ã§ã¯thread_ioã¨thread_entryï¼ãå¿ è¦ã«ãªãã¾ãã