Код бенчмарка для lock-free

  1. #define N1 3
  2. #define N2 1000000
  3. static int
  4. do_rand(unsigned long ctx)
  5. {
  6. /*
  7. * Compute x = (7^5 * x) mod (2^31 - 1)
  8. * wihout overflowing 31 bits:
  9. * (2^31 - 1) = 127773 * (7^5) + 2836
  10. * From "Random number generators: good ones are hard to find",
  11. * Park and Miller, Communications of the ACM, vol. 31, no. 10,
  12. * October 1988, p. 1195.
  13. */
  14.     long hi, lo, x;
  15.     /* Can't be initialized with 0, so use another value. */
  16.     if (ctx == 0)
  17.         ctx = 123459876;
  18.     hi = ctx / 127773;
  19.     lo = ctx % 127773;
  20.     x = 16807 * lo - 2836 * hi;
  21.     if (x < 0)
  22.         x += 0x7fffffff;
  23.     return x;
  24. }
  25. long commonContext;
  26. char fill[54];
  27. struct Tls
  28. {
  29.     long individualContext;
  30.     long myRandomContext;
  31.     int outCounter;
  32.     char fill[54];
  33. } tls[30];
  34. HANDLE manual = CreateEvent(0, TRUE, FALSE, 0);
  35. int moda;
  36. DWORD WINAPI threadFunc1(LPVOID lpThreadParameter)
  37. {
  38.     Tls& me = tls[(int) lpThreadParameter];
  39.     me.myRandomContext = (int)&lpThreadParameter;
  40.     long& C = commonContext;
  41.     const int myModa = moda;
  42.     WaitForSingleObject(manual, INFINITE);
  43.     for(int i=0;i<N1;++i)
  44.         for(int j=0;j<N2;++j)
  45.         {
  46.             long oldVal = C;
  47.             for(;;)
  48.             {
  49.                 long newVal = InterlockedCompareExchange(&C, do_rand(oldVal), oldVal);
  50.                 if (newVal == oldVal)
  51.                     break;
  52.                 else
  53.                 {
  54.                     oldVal = newVal;
  55.                 }
  56.             }
  57.             me.myRandomContext = do_rand(me.myRandomContext);
  58.             int limit=(me.myRandomContext %myModa);
  59.             for(int k=0;k<limit;++k)
  60.                 me.outCounter+=limit+10;
  61.         }
  62.     return 0;
  63. }
  64. CRITICAL_SECTION cs;
  65. DWORD WINAPI threadFunc2(LPVOID lpThreadParameter)
  66. {
  67.     Tls& me = tls[(int) lpThreadParameter];
  68.     me.myRandomContext = (int)&lpThreadParameter;
  69.     const int myModa = moda;
  70.     long& C = commonContext;
  71.     WaitForSingleObject(manual, INFINITE);
  72.     for(int i=0;i<N1;++i)
  73.         for(int j=0;j<N2;++j)
  74.         {
  75.             EnterCriticalSection(&cs);
  76.             C = do_rand(C);
  77.             LeaveCriticalSection(&cs);
  78.             me.myRandomContext = do_rand(me.myRandomContext);
  79.             int limit =(me.myRandomContext %myModa);
  80.             for(int k=0;k<limit;++k)
  81.                 me.outCounter+=limit+10;
  82.         }
  83.         return 0;
  84. }
  85. int step(int n)
  86. {
  87.     int retval = n / 5;
  88.     if (retval==0)
  89.         retval = 1;
  90.     return retval;
  91. }
  92. int _tmain(int argc, _TCHAR* argv[])
  93. {
  94.     InitializeCriticalSection(&cs);
  95.     HANDLE threads[100];
  96.     unsigned start;
  97.     int tnum=8;
  98.     moda=1000;
  99. //    for(moda=1; moda<20000;moda+=step(moda))
  100.     for (tnum=1;tnum<=18;tnum++)
  101.     {
  102.         for(int i=0;i<tnum;++i)
  103.         {
  104.             DWORD tid;
  105.             threads[i]=CreateThread(NULL, 0, threadFunc1, (void*)i, 0, &tid );
  106.         }
  107.         Sleep(1000); // naive but enough for dirty test
  108.         start = GetTickCount();
  109.         SetEvent(manual);
  110.         for(int i=0;i<tnum;++i)
  111.         {
  112.             WaitForSingleObject(threads[i], INFINITE);
  113.         }
  114.         int v1 = GetTickCount()-start;
  115.         ResetEvent(manual);
  116.         for(int i=0;i<tnum;++i)
  117.         {
  118.             DWORD tid;
  119.             threads[i]=CreateThread(NULL, 0, threadFunc2, (void*)i, 0, &tid );
  120.         }
  121.         Sleep(1000);
  122.         start = GetTickCount();
  123.         SetEvent(manual);
  124.         for(int i=0;i<tnum;++i)
  125.         {
  126.             WaitForSingleObject(threads[i], INFINITE);
  127.         }
  128.         int v2 = GetTickCount()-start;
  129.         ResetEvent(manual);
  130.         printf("%d %d %f %f\n", tnum, moda,(double(tnum)*1000.)/v1,(double(tnum)*1000.)/v2);
  131.     }
  132.     return 0;
  133. }
#define N1 3
#define N2 1000000


static int
do_rand(unsigned long ctx)
{
/*
 * Compute x = (7^5 * x) mod (2^31 - 1)
 * wihout overflowing 31 bits:
 *      (2^31 - 1) = 127773 * (7^5) + 2836
 * From "Random number generators: good ones are hard to find",
 * Park and Miller, Communications of the ACM, vol. 31, no. 10,
 * October 1988, p. 1195.
 */
	long hi, lo, x;

	/* Can't be initialized with 0, so use another value. */
	if (ctx == 0)
		ctx = 123459876;
	hi = ctx / 127773;
	lo = ctx % 127773;
	x = 16807 * lo - 2836 * hi;
	if (x < 0)
		x += 0x7fffffff;
	return x;
}

long commonContext;
char fill[54];

struct  Tls
{
	long individualContext;
	long myRandomContext;
	int outCounter;
	char fill[54];
} tls[30];

HANDLE manual = CreateEvent(0, TRUE, FALSE, 0);

int moda;
DWORD WINAPI threadFunc1(LPVOID lpThreadParameter)
{
	Tls& me = tls[(int) lpThreadParameter];
	me.myRandomContext = (int)&lpThreadParameter;
	long& C = commonContext;
	const int myModa = moda;
	WaitForSingleObject(manual, INFINITE);
	for(int i=0;i<N1;++i)
		for(int j=0;j<N2;++j)
		{
			long oldVal = C;
			for(;;)
			{
				long newVal = InterlockedCompareExchange(&C, do_rand(oldVal), oldVal);
				if (newVal == oldVal)
					break;
				else
				{
					oldVal = newVal;
				}
			}
			me.myRandomContext = do_rand(me.myRandomContext);
			int limit=(me.myRandomContext %myModa);
			for(int k=0;k<limit;++k)
				me.outCounter+=limit+10;
		}

	return 0;
}

CRITICAL_SECTION cs;



DWORD WINAPI threadFunc2(LPVOID lpThreadParameter)
{
	Tls& me = tls[(int) lpThreadParameter];
	me.myRandomContext = (int)&lpThreadParameter;
	const int myModa = moda;

	long& C = commonContext;
	WaitForSingleObject(manual, INFINITE);
	for(int i=0;i<N1;++i)
		for(int j=0;j<N2;++j)
		{
			EnterCriticalSection(&cs);
			C = do_rand(C);
			LeaveCriticalSection(&cs);
			me.myRandomContext = do_rand(me.myRandomContext);
			int limit =(me.myRandomContext %myModa);
			for(int k=0;k<limit;++k)
				me.outCounter+=limit+10;
		}

		return 0;
}

int step(int n)
{
	int retval = n / 5;
	if (retval==0)
		retval = 1;
	return retval;

}

int _tmain(int argc, _TCHAR* argv[])
{
	InitializeCriticalSection(&cs);
	HANDLE threads[100];
	unsigned start;
	int tnum=8;
	moda=1000;
//	for(moda=1; moda<20000;moda+=step(moda))
	for (tnum=1;tnum<=18;tnum++)
	{
		for(int i=0;i<tnum;++i)
		{
			DWORD tid;
			threads[i]=CreateThread(NULL, 0, threadFunc1, (void*)i, 0,  &tid );
		}
		Sleep(1000); // naive but enough for dirty test
		start = GetTickCount();
		SetEvent(manual);
		for(int i=0;i<tnum;++i)
		{
			WaitForSingleObject(threads[i], INFINITE);
		}
		int v1 = GetTickCount()-start;
		ResetEvent(manual);

		for(int i=0;i<tnum;++i)
		{
			DWORD tid;
			threads[i]=CreateThread(NULL, 0, threadFunc2, (void*)i, 0,  &tid );
		}
		Sleep(1000);
		start = GetTickCount();
		SetEvent(manual);
		for(int i=0;i<tnum;++i)
		{
			WaitForSingleObject(threads[i], INFINITE);
		}
		int v2 = GetTickCount()-start;
		ResetEvent(manual);


		printf("%d %d %f %f\n", tnum, moda,(double(tnum)*1000.)/v1,(double(tnum)*1000.)/v2);
	}
	return 0;
}