ãã¹ãã³ã¼ã 1ï¼
ãã«ãã¹ã¬ããç°å¢ã§ new (delete) ãé£çºãããã¨ã«ä¸»ç¼ãããã¦ãã¾ãï¼4 ã¹ã¬ãã並å*1ï¼4096 è¦ç´ ã®ãã¤ã³ã¿é
åãç¨æãã¦ï¼ã«ã¼ãæ¯ã«æ°ããªã¤ã³ã¹ã¿ã³ã¹ãçæããã¤ã³ãå
ãç½®ãæãã¦ããã¾ãï¼åã¤ã³ã¹ã¿ã³ã¹ã¯ã©ã³ãã ã«æåæ°ã 1ã16 ããé¸ãã æååã¯ã©ã¹ã§ãï¼ç似乱æ°åã®çæ㯠MersenneTwister æ³ã§çµ±ä¸ãã¾ããï¼C++ çã§ã¯ç½®ãæãæã®ã¿ã¤ãã³ã°ã§å¤ãã¤ã³ã¹ã¿ã³ã¹ã delete ãã¾ãï¼ã«ã¼ãæ¯ã«ãã¤ã³ã¿é
åãç°ãªãé åºã§ã¹ãã£ã³ããããã«ç´°å·¥ããã¦ããã¾ãï¼
以ä¸ã½ã¼ã¹ã³ã¼ãã§ãï¼MersenneTwister ã«ããä¹±æ°çæã«ã¼ãã³ã«ã¤ãã¦ã¯ãªã³ã¯å
ããå
¥æãã¦ãã ããï¼C++ çã¯ã¡ããã¨ãã«ãã¹ã¬ããçã® CRT ã¨ãªã³ã¯ãã¾ããããï¼ãå
ããã¨ã®ç´æã§ãï¼
C#çï¼
using System; using System.Text; using System.Threading; class Bench1 { static void Main(string args) { const int numThread = 4; using( ManualResetEvent beginNotify = new ManualResetEvent(false) ) { WaitHandle waitHandles = new WaitHandle[ numThread ]; ThreadTest tests = new ThreadTest[numThread]; Random rand = new Random(); for( int i = 0; i < tests.Length; ++i ) { tests[i] = new ThreadTest( string.Format( "Worker Thread {0}", i ), beginNotify, rand.Next() ); waitHandles[i] = tests[i].EndNotify; tests[i].ThreadStart(); } Thread.Sleep(1000); DateTime begin = DateTime.Now; beginNotify.Set(); WaitHandle.WaitAll( waitHandles ); foreach( ThreadTest test in tests ) { test.Dispose(); } DateTime end = DateTime.Now; TimeSpan el = end - begin; Console.WriteLine( el.ToString() ); } } } internal class ThreadTest : IDisposable { private const long LoopNum = 4096; private readonly Thread _thread; private readonly Random _rand; private readonly WaitHandle _beginNotify; public readonly ManualResetEvent EndNotify; public ThreadTest(string name, WaitHandle beginNotify, int seed) { this._thread = new Thread( new ThreadStart( this.ThreadMain ) ); this._thread.Name = name; this.EndNotify = new ManualResetEvent(false); this._beginNotify = beginNotify; this._rand = new jp.takel.PseudoRandom.MersenneTwister( (uint) seed ); } public void ThreadMain() { this._beginNotify.WaitOne(); string buf = new string[ LoopNum ]; for( long mul = LoopNum; mul > 0; --mul ) { for( long i = 0; i < LoopNum; ++i ) { buf[ (i * mul) % LoopNum ] = new string( '!', this._rand.Next( 1, 16 ) ); } } this.EndNotify.Set(); } public void ThreadStart() { this._thread.Start(); } #region IDisposable ã¡ã³ã public void Dispose() { (this.EndNotify as IDisposable).Dispose(); } #endregion }
C++ çï¼
#include <windows.h> #include <string> #include "MersenneTwister.h" struct ThreadTest { static const __int64 LoopNum = 4096; HANDLE EndNotify; ThreadTest( const std::wstring& name, HANDLE beginNotify, DWORD seed ) : _rand(seed), _name(name), _beginNotify(beginNotify) { DWORD id; EndNotify = CreateEvent( NULL, TRUE, FALSE, name.c_str() ); _thread = CreateThread( NULL, 0, ThreadMainStub, static_cast<void*>(this), CREATE_SUSPENDED, &id ); } void ThreadStart() { ResumeThread( _thread ); } ~ThreadTest() { WaitForSingleObject( _thread, 10000 ); CloseHandle( _thread ); CloseHandle( EndNotify ); } private: MTRand _rand; HANDLE _thread; HANDLE _beginNotify; std::wstring _name; static DWORD WINAPI ThreadMainStub( void* ptr ) { return static_cast<ThreadTest*>(ptr)->ThreadMain(); } DWORD WINAPI ThreadMain() { WaitForSingleObject( _beginNotify, INFINITE ); std::wstring* buf[ LoopNum ]; for( int i = 0; i < LoopNum; ++i ) { buf[i] = NULL; } for( __int64 mul = LoopNum; mul > 0; --mul ) { for( __int64 i = 0; i < LoopNum; ++i ) { const int index = (i * mul) % LoopNum; if( buf[index] != NULL ) { delete buf[index]; } buf[ index ] = new std::wstring( '!', _rand.randInt( 15 ) + 1 ); } } for( int i = 0; i < LoopNum; ++i ) { if( buf[i] != NULL ) { delete buf[i]; } } SetEvent( EndNotify ); ExitThread(0); } }; int main() { const int numThread = 4; HANDLE beginNotify = CreateEvent( NULL, TRUE, FALSE, L"begin notify" ); HANDLE waitHandles[ numThread ]; { ThreadTest* tests[ numThread ]; srand( GetTickCount() ); for( int i = 0; i < numThread; ++i ) { wchar_t buf[ 64 ]; wsprintf( buf, L"Worker Thread %d", i ); tests[i] = new ThreadTest( buf, beginNotify, rand() ); waitHandles[i] = tests[i]->EndNotify; tests[i]->ThreadStart(); } Sleep(1000); const DWORD begin = GetTickCount(); SetEvent( beginNotify ); WaitForMultipleObjects( numThread, waitHandles, TRUE, INFINITE ); const DWORD end = GetTickCount(); const DWORD min = (end - begin) / 60000; const DWORD sec = (end - begin - 60000 * min) / 1000; const DWORD msec = (end - begin - 60000 * min - 1000 * sec); wprintf( L"%d:%d.%d\n", min, sec, msec ); for( int i = 0; i < numThread; ++i ) { delete tests[i]; } } return 0; }
æå
ã®ç°å¢*2ã§ã¯ç¡è¦ã§ããªãç¨åº¦ã®å·®ã¯ã¤ãã¦ãã¾ã*3ï¼
VTune ã§è¦ã¦ã¿ãã¨ï¼C++ çã§ã¯å
¨ CPU æéã®å®ã«ç´ååãã¡ã¢ãªå¦çã«æ¶è²»ããã¦ãã¾ã£ã¦ãã¾ãï¼å
·ä½çã«ã¯ãã¼ã管çç¨ãªã³ã¯ãªã¹ãæä½æã® lock å¦çãæãå¤ãã®æéãæ¶è²»ãã¦ããï¼RtlFreeHeapï¼RtlAllocateHeap ã®é ã«ç¶ãã¾ãï¼ãããã¾ãã ãã¨ãåãã®æ¹ã¯ãVisual C++ ã®æ¦å¿µ: æ©è½ã®è¿½å ãã¼ã競åã®åé¿ãããããã©ããï¼ãã ãã®å¯¾çããã£ã¦ãã¦ãï¼RtlFreeHeap 㨠RtlAllocateHeap ãé«ã³ã¹ããå½±é¿ãã¦ï¼å¤§ããããã©ã¼ãã³ã¹ãæ¹åãããã¨ãããã¨ã¯ããã¾ããã§ããï¼
*1:ããã¯åã«ãã¡ã® PC ç°å¢ã XEONÃ2 ã§ãããã¨ã«ç±æ¥ãã¾ã
*2:Intex Xeon(Prestonia) 2.0GHz Ã2ï¼DDR DPC2100 ECC 1536MBï¼Windows XP Professional SP1ï¼.NET Framework 1.1 SP1ï¼Visual C++ .NET 2003, Visual C# 2003
*3:.NET Framework EULA ã®ããã³ããã¼ã¯çµæå
¬éç¦æ¢æ¡é
ãããã£ã¦ï¼ãã©ããããå·®ãä»ãããã¯ä¼ãã¦ããã¾ãï¼ãã®ç¨åº¦ã®ãã¿ã§ã¯æ¢ãã¦ãªã¹ã¯ã¯ç¯ããããªãã¨ãããã¨ã§ï¼æ¡é
ãã®ãã®ã®æå¹æ§ã«ã¤ãã¦ãæ°ã«ãªãã¨ããã§ã¯ããã¾ããã©ãï¼
http://www.itmedia.co.jp/news/0301/23/ne00_benchmark.html
ã©ã¤ã»ã³ã¹ãå¤æ´ããã¦æ¡ä»¶ä»ãã§ãã³ããã¼ã¯çµæã¯å
¬éå¯ã§ãï¼