ã¹ã¬ããéã®ãã¼ã¿ã®ããåãã«std::vector<t>ã¯åããªã
ã5å¹´è¿ãåã®ã¢ã¼ãã£ã¯ã«ï¼ãC++11:ã¹ã¬ããã»ã©ã¤ãã©ãªã²ã¨ããããã§ã10ä¸æªæºã®ç´ æ°ã®ç·æ°ãæ±ãããµã³ãã«ã示ãã¾ãããããããã¼ã¹ã«ãç´ æ°ã®åæ°ãæ±ããã ãã§ãªããè¦ã¤ããç´ æ°ï¼int pãå¼æ°ã«é¢æ°ãªãã¸ã§ã¯ãf(int)ãå¼ã¶ããå°ãã°ããæãå ãã¾ããé¢æ°ãªãã¸ã§ã¯ãå ã§std::vector<int<>ã«è¦ã¤ããç´ æ°pã追å ï¼push_back(p)ï¼ãã¾ããã·ã³ã°ã«ã¹ã¬ããã ã¨ãããªã³ã¼ãã«ãªãã¾ããã
#ifndef PRIME_H_ #define PRIME_H_ #include <mutex> #include <functional> #include <cmath> // nã¯ç´ æ°ï¼ inline bool is_prime(int n) { int sqn = (int)sqrt((float)n) + 1; if ( n == 2 || n == 3 ) return true; // 2,3ã¯ç´ æ° if ( n % 2 == 0 ) return false; // ï¼2ãé¤ãï¼å¶æ°ã¯ç´ æ°ãããªã // 3以ä¸ã®å¥æ°ã§å²ãããç´ æ°ãããªã for ( int i = 3; i < sqn; i += 2 ) { if ( n % i == 0 ) { return false; } } return true; } // lo以ä¸hiæªæºã®ç´ æ° x ã«å¯¾ã f(x) ããç·æ°ãè¿ã template<typename Function> int count_prime(int lo, int hi, Function f) { int count = 0; for ( int i = lo; i < hi; ++i ) { if ( is_prime(i) ) { f(i); ++count; } } return count; } #endif
/* single-thread ã§ç´ æ°ãè¦ã¤ãã */ #include <iostream> #include <chrono> #include "prime.h" template<typename C> int single(int M, C& c) { using namespace std; chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now(); int count = count_prime(2, M, [&](int p) { c.push_back(p); } ); chrono::high_resolution_clock::time_point stop = chrono::high_resolution_clock::now(); chrono::milliseconds duration = chrono::duration_cast<chrono::milliseconds>(stop - start); cout << duration.count() << " [ms]" << endl; return count; } #include <vector> int main() { using namespace std; const int M = 500000; vector<int> primes; int count = single(M, primes); if ( count == primes.size() ) { cout << count << " primes found." << endl; } else { cout << "oops, " << count << " != " << primes.size() << endl; } }
ã2以ä¸Mæªæºã®ç´ æ°ãã³ã¬ã§æ±ã¾ãã¾ããç¯å²"2以ä¸Mæªæº"ãçåã«åå²ããåç¯å²ã«ããç´ æ°ãããããç¬ç«ããã¹ã¬ããã«è¦ã¤ãã¦ãããã¾ãã
#ifndef DIV_RANGE_H_ #define DIV_RANGE_H_ 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 t) const { return lo_ + stride_ * t; } T hi(int t) const { return (++t < n_) ? lo_ + stride_ * t : hi_; } }; #endif
#include <iostream> #include <chrono> #include <thread> #include <future> #include <vector> #include "prime.h" #include "div_range.h" template<typename Function> int multi(int M, Function f, int nthr) { using namespace std; vector<future<int>> futures; // 2以ä¸Mæªæºã®ç¯å²ãnthrçåãããããããåå¥ã®threadã«åæ ããã div_range<int> rng(2, M, nthr); chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now(); for ( int i = 0; i < nthr; ++i ) { // async()ã§threadãèµ·ãã futures.emplace_back(async(count_prime<Function>, rng.lo(i), rng.hi(i), f)); } // åthreadããå¾ãããçµæ(ç´ æ°ã®åæ°)ãç©ç®ãã int count = 0; for ( auto& fut : futures ) { count += fut.get(); } chrono::high_resolution_clock::time_point stop = chrono::high_resolution_clock::now(); chrono::milliseconds duration = chrono::duration_cast<chrono::milliseconds>(stop - start); cout << nthr << " thread(s) found " << count << " primes in " << duration.count() << " [ms]" << endl; return count; } int main() { using namespace std; const int M = 500000; vector<int> primes; for ( int nthr = 1; nthr <= 10; ++nthr ) { primes.clear(); int count = multi(M, [&](int p) { primes.push_back(p); }, nthr); if ( count != primes.size() ) { cout << "oops, " << count << " != " << primes.size() << endl; } } }
ãå®è¡ãããã°ããããªæ®å¿µãªçµæã¨ãªãã¾ããã
ãæ£ããåãã¦ãããªãmulti()ãè¿ãç´ æ°ã®ç·æ°ã¨ vectorå ã®è¦ç´ æ°ï¼primes.size()ã¯ä¸è´ããã¯ãã§ããããã«ãã¹ã¬ããã ã¨å¾è ãå°ãªç®ã«ãªã£ã¦ãã¾ããã
ãè¤æ°ã®ã¹ã¬ãããåæã«push_back()ãããã¨ã§ãã¼ã¿ç«¶åï¼data raceï¼ãçºçããã®ã§ããããæå¾ã¾ã§åããã ãã§ãã©ããã¼ã§ããpush_back()ã®éã«ã¯vectorå é¨ã§ã¡ã¢ãªã®ç¢ºä¿ï¼è§£æ¾ããã³ãã¤ã³ã¿ã®ä»ãæ¿ããè¡ããããããã¡ã¢ãªã®ã¢ã¯ã»ã¹ã¨ã©ã¼ã§ç°å¸¸åæ¢ãã¦ãä¸æè°ã§ã¯ããã¾ãããããã
ãè¤æ°ã®ã¹ã¬ãããvectorã«å¯¾ãåææ°ã¾ã¾ã«è¦ç´ ãæãè¾¼ãã®ããã©ãã«ã®åå ãªã®ã§ãããã1ã¤ã®ã¹ã¬ãããpush_back()ãã¦ããéãä»ã®ã¹ã¬ãããpush_back()ã§ããªããããããã¯ãã¦ããã°æ£ããçµæãå¾ãããã§ããããé¢æ°ãªãã¸ã§ã¯ãå ã§mutexã使ã£ã¦æä»å¶å¾¡ãã¦ã¿ã¾ããããã
... #include <mutex> int main() { using namespace std; const int M = 500000; vector<int> primes; mutex mtx; for ( int nthr = 1; nthr <= 10; ++nthr ) { primes.clear(); int count = multi(M, [&](int p) { mtx.lock(); primes.push_back(p); mtx.unlock(); }, nthr); if ( count != primes.size() ) { cout << "oops, " << count << " != " << primes.size() << endl; } } }
ã1ã¤ã®ã¹ã¬ãããvectorã«è¦ç´ ãæ¿å ¥ï¼push_backï¼ãã¦ããéã¯ä»ã®ã¹ã¬ããã®push_backãmutexã§ãããã¯ããã¦åããªãããããã©ã¼ãã³ã¹ã¯ã»ãã®å°ãä½ä¸ãã¾ããã©ãè¦ç´ æ¿å ¥ã®é »åº¦ããã»ã©ã«å¤§ãããªããã°åå使ããã§ããããã
ãããããªããå®éã®ã¢ããªã±ã¼ã·ã§ã³ã§ã¯æ¡ä»¶ãããã·ãã¢ã«ãªãå¾ã¾ããã¹ã¬ããéã§ã³ã³ãããå ±æï¼å ±ç¨ãããã·ãã¥ã¨ã¼ã·ã§ã³ã§ã¯ãã³ã³ããã«è¦ç´ ãæ¸ãã¦ãããããããè¦ç´ ãèªãã§ãã¹ã¬ããã®æ¹ãå¤ããªããã¨ãèãããã¾ããã³ã³ããå ã®è¦ç´ ãèªãã§ä¸é£ã®å¦çãè¡ãã¨ãããã¨ã¯ãã³ã³ãããæä¾ããã¤ãã¬ã¼ã¿ãä»ãã¦è¦ç´ ã«ã¢ã¯ã»ã¹ãããã¨ãæå³ãã¾ãã
for ( auto iter = c.begin(); iter != c.end(); ++iter ) { // *iterãèªãã§ãªãããã }
ã¿ããã«ãããã® for-loop ãåã£ã¦ããéã¤ãã¬ã¼ã¿ã¯å¸¸ã«æå¹ã§ãªãã¦ã¯ãªãããã¤ãã¬ã¼ã¿ã®æãå ãå¤åãã¦ã¯å°ãã¾ããå¾ã£ã¦ã³ã³ããå ã®è¦ç´ ã¯ä»ã®ã¹ã¬ãããåæã«åé¤ï¼ç§»åãã¦ã¯ãªãã¾ããã
ããã®æ¡ä»¶ãæºããã®ã«æãå®ç´ãªè§£æ±ºçã¯ãã¤ãã¬ã¼ã¿ã使ããã¦ããæéãä¸ã®ä¾ã§ã¯for-loopãåã£ã¦ããéãmutexãç¨ãããã¨ã§ä»ã®ã¹ã¬ããããã®å²ãè¾¼ã¿ããããã¯ãããã¨ãªã®ã§ããããããªãã¨ãã¡ããã¨ã¹ã¬ããã®ã©ãã1ã¤ãã³ã³ãããæä½ãã¦ããéã¯ä»ã®å ¨ã¹ã¬ãããã³ã³ããæä½ããããã¯ãããã·ã³ã°ã«ã¹ã¬ããã§åãã¦ãã®ã¨å¤§å·®ãªããªã£ã¡ããã¾ããmutexãªã©ã§æä»å¶å¾¡ããæéã極åå°ããæããªãã¨ãã«ãã¹ã¬ããã®æ¨å³ããªããªã£ã¦ãã¾ãã¾ãã
ãå ãã¦å°ã£ããã¨ã«ãstd::vectorã¯è¦ç´ ã®åé¤æã ããããªãæ¿å ¥æã«ãã¤ãã¬ã¼ã¿ãç¡å¹ã¨ãªããã¨ãããã¾ããstd::vector<t> vããã£ã¦ãstd::vector<t>::iter = v.begin()ã«ãã£ã¦å é è¦ç´ ãæãã¤ãã¬ã¼ã¿ãæã«å ¥ããã®ã¡ãv.insert()ï¼push_back()ï¼emplace_back() ãè¡ãã¨ãã®ç¬éiterãç¡å¹ã¨ãªãå¾ããã§ããã以ä¸ã³ã¼ãã§ãã®æ§åã観å¯ãã¾ãããã
#include <iostream> #include <vector> using namespace std; /* ã³ã³ããã®å é ä½ç½®ãããã³åè¦ç´ ã®å é ããã®è·é¢ï¼ãã¤ãæ°ï¼ */ template<typename C> void print_layout(C& c) { for (int i = 0; i < 20; ++i) { c.push_back(i); char* frontptr = (char*)&c[0]; cout << (void*)frontptr << " : "; for (int j = 0; j < c.size(); ++j) { cout << (int)((char*)&c[j] - frontptr) << " "; } cout << endl; } } int main() { std::vector<int> v; cout << "std::vector<int>\n"; print_layout(v); concurrency::concurrent_vector<int> cv; cout << "\nconcurrency::concurrent_vector<int>\n"; print_layout(cv); }
ãã»ãããpush_back()ããã¨åè¦ç´ ã®ã¢ãã¬ã¹ã丸ãã¨æ¸ãæãããã¨ããããã§ããå½ç¶ã£ã¡ãå½ç¶ã®æåã§ãã¦ãstd::vector<t>å ã«ã¯ã¡ã¢ãªé åã確ä¿ããã¦ãã¦ããã®é åã«è¦ç´ åãæ ¼ç´ããã¦ãã¾ããè¦ç´ ã®æ¿å ¥ã«ãã£ã¦ç¢ºä¿ããã¦ããã¡ã¢ãªé åã溢ãããã«ãªãã¨ããã大ããªï¼æ°ããªï¼é åã確ä¿ãï¼ç¾é åããæ°é åã«è¦ç´ åãã³ãã¼ãã¦ï¼ç¾é åã解æ¾ãã¾ãããã®ã¨ãã¤ãã¬ã¼ã¿ã®æãå ã解æ¾ããã¦ç¡å¹ã¨ãªãã¾ãã
ããããªããã§ãã¹ã¬ããéã§ãã¼ã¿ãããåãããæ段ã¨ãã¦std::vector<t>ã¯ï¼æä»ãã¹ãç¯å²ããã¾ãã«åºãããã§ï¼åãã¦ãªããã¨ãããã¨ã«ã