compiler vc2010 and gcc4.5.2(minGW)
os : windows xp sp3
I am trying to implement a generic find_if function as std::find_if
Below is my code

//code for estimating expanding time
template<typename unaryOP>
double timeCount(unaryOP op, size_t const LOOP = 1, char const* NAME = "function")
{
  std::clock_t begin, end;
  begin = std::clock();
  for(size_t i = 0; i != LOOP; ++i) op();
  end = std::clock();
  double const RESULT = (end - begin) / static_cast<double>(CLOCKS_PER_SEC);
  size_t const HOUR = static_cast<size_t>(RESULT / 3600);
  size_t const MIN = static_cast<size_t>(RESULT) / 60 - HOUR * 60;
  double const SEC = RESULT - static_cast<double>(MIN * 60 + HOUR * 3600);
  std::cout<<"time of the(hours : min : sec) "<<NAME<<" : "<<HOUR<<" : "<<MIN<<" : "<<SEC;
  std::cout<<"\nloop "<<LOOP<<" times\n";
  return RESULT;
}


int findInt(void const *DATA)
{		
	if(*(int*)DATA > 10000) return 1;
	else return 0;
}

void* CFind(void *base, size_t const NUM, size_t const SIZE, int(*compare)(void const *DATA) )
{	
	size_t i = 0;
  for(i = 0; i != NUM; ++i)
	{
		if(compare(base)) break;
		base = (char*)(base) + SIZE;
	}
	return base;
}

void testCFind()
{	
	int data[] = {1, 20, 33, 55, 22, 77, 88, 99, 3000, 8880, 800, 777, 345, 976, 345, 222, 111, 0, 77, 88, 99, 1, 2, 3, 20000};	
	size_t i = 0;
	size_t const NUM = 1E6;
	for(i = 0; i != NUM; ++i) void *temp = CFind(&data[0], sizeof(data) / sizeof(*data), sizeof(*data), findInt);	
}

class IntFind : public std::unary_function<int, bool>
{
  public :
	  bool const operator()(int const A) const {return A > 10000;}
};

template<typename inItr, typename predicate>
inItr myFind_if(inItr first, inItr last, predicate pred)
{
	while(first != last)
	{
		if(pred(*first)) break;
		++first;
	}
	return first;
}

void testCPPFind()
{
	int data[] = {1, 20, 33, 55, 22, 77, 88, 99, 3000, 8880, 800, 777, 345, 976, 345, 222, 111, 0, 77, 88, 99, 1, 2, 3, 20000};
	size_t const NUM = 1E6;
	for(size_t i = 0; i != NUM; ++i)
	auto it = std::find_if(&data[0], &data[0] + sizeof(data) / sizeof(*data), IntFind());
	//auto it = myFind_if(&data[0], &data[0] + sizeof(data) / sizeof(*data), IntFind());
	
}

void testCPPFind2()
{
	int data[] = {1, 20, 33, 55, 22, 77, 88, 99, 3000, 8880, 800, 777, 345, 976, 345, 222, 111, 0, 77, 88, 99, 1, 2, 3, 20000};
	size_t const NUM = 1E6;
	for(size_t i = 0; i != NUM; ++i)
	auto it = myFind_if(&data[0], &data[0] + sizeof(data) / sizeof(*data), IntFind());
}

int main()
{
  timeCount(testCPPFind, 1E2, "testCPPFind");
  timeCount(testCPPFind2, 1E2, "testCPPFind2");
  timeCount(testCFind, 1E7, "testCFind");	
		
  std::cout<<"system pause"<<std::endl;
  std::cin.get();
  return 0;
}

The results of vc2010 are

testCPPFind = 2.031;
testCPPFind2 = 1.969;
testCFind = 0.047;

The results of GCC are almost equal
What makes the speed of CFind far more faster than myFind_if and std::findif?
Thanks a lot

Edited 5 Years Ago by stereomatching: n/a

timeCount(testCPPFind, 1E2, "testCPPFind");
timeCount(testCPPFind2, 1E2, "testCPPFind2");
timeCount(testCFind, 1E7, "testCFind");             <--- Why not 1E2?? Its different from the other two functions before it..

Could also be that CFind does less work.. Not sure

<--- Why not 1E2?? Its different from the other two functions before it..

Because the time of 1E2 is too small for testCFind(it would be 0)
This also indicate that on vs2010, the speed of void* is far more faster than
std::find_if and myFind_if since testCFind call more than 10000 times than
testCPPFind and testCPPFind2

The problem of optimization? I thought that vsc++ after 2005 should be a good IDE
for most of the cases

Thanks

Edited 5 Years Ago by stereomatching: n/a

I test another codes on vs2010

void* CFind3(void* begin, void* end, int const VALUE)
{
  while(begin != end)
  {
    if(*(int*)begin == VALUE) break;
    begin = (char*)begin + 4;
  }
  return begin;
}

void* CFind4(void *base, size_t const NUM, int const DATA)
{	
  size_t i = 0;
  for(i = 0; i != NUM; ++i)
  {
	if(*(int*)base == DATA) break;
	base = (char*)(base) + 4;
  }
  return base;
}

CFind4 is much more faster than CFind3

I guess the penalty is come from this line

while(begin != end)

But this kind of code is always seen in generic code of c++
could this mean the generic code generate by vc2010 could be very slow?
Is this a well known defect of vc2010 or it is my mistake to produce this
kind of crap code?Thanks a lot

Might I suggest looking at the assembly output for your code? You might be enlightened as to what the code generator is doing. :)

Might I suggest looking at the assembly output for your code? You might be enlightened as to what the code generator is doing. :)

This could be a good idea if i am good at assembly(only know a little bit of it)
But this maybe a good way to solve this puzzle and learn how to decipher assembly
But there are still one problem, even I know what the code generator is doing,
the problem still exist, should I report this kind of problem to ms?Or this is
a difficult problem ms could not solve?

ps : how could I dumb the assembly code out from vs2010?Thanks

Edited 5 Years Ago by stereomatching: n/a

Something is wrong here.

I run your code (BTW it doesn't compile as is, and produces some warnings), and got the following results (also note that I changed the test loop count to 1E2):
time of the(hours : min : sec) testCPPFind : 0 : 0 : 18.03
loop 100 times
time of the(hours : min : sec) testCPPFind2 : 0 : 0 : 17.69
loop 100 times
time of the(hours : min : sec) testCFind : 0 : 0 : 22.21
loop 100 times

which is a very reasonable outcome (for a record, compiled with -g and -O0 gcc version 4.1.2 (Gentoo 4.1.2 p1.1) ).

However, the compiler warnings, namely converting to ‘size_t’ from ‘double’ and passing ‘double’ for argument 2 to ‘double timeCount(unaryOP, size_t, const char*) make me very suspicious. Get rid of them; rerun the test. If the problem persists, post the exact code you are running.

However, the compiler warnings

I know it would give such warning, it is cause by type conversion(double to size_t)
since I didn't cast it explicitly(you could get rid of it by adding static_cast<size_t>)
The result of gcc are fine for me too, but it has a big different on visual c++ 2010

This article has been dead for over six months. Start a new discussion instead.