我在STL中使用set_intersection交叉一组100,000个数字和一组1,000个数字,并且花费21秒,在C#中花费11ms。
C ++代码:
int runIntersectionTestAlgo()
{
set<int> set1;
set<int> set2;
set<int> intersection;
// Create 100,000 values for set1
for ( int i = 0; i < 100000; i++ )
{
int value = 1000000000 + i;
set1.insert(value);
}
// Create 1,000 values for set2
for ( int i = 0; i < 1000; i++ )
{
int random = rand() % 200000 + 1;
random *= 10;
int value = 1000000000 + random;
set2.insert(value);
}
set_intersection(set1.begin(),set1.end(), set2.begin(), set2.end(), inserter(intersection, intersection.end()));
return intersection.size();
}
C#代码:
static int runIntersectionTest()
{
Random random = new Random(DateTime.Now.Millisecond);
Dictionary<int,int> theMap = new Dictionary<int,int>();
List<int> set1 = new List<int>();
List<int> set2 = new List<int>();
// Create 100,000 values for set1
for ( int i = 0; i < 100000; i++ )
{
int value = 1000000000 + i;
set1.Add(value);
}
// Create 1,000 values for set2
for ( int i = 0; i < 1000; i++ )
{
int value = 1000000000 + (random.Next() % 200000 + 1);
set2.Add(value);
}
// Now intersect the two sets by populating the map
foreach( int value in set1 )
{
theMap[value] = 1;
}
int intersectionSize = 0;
foreach ( int value in set2 )
{
int count;
if ( theMap.TryGetValue(value, out count ) )
{
intersectionSize++;
theMap[value] = 2;
}
}
return intersectionSize;
}
}
答案 0 :(得分:8)
一些事情会使你的两个例子更具可比性。
首先,您在STL中的示例不太正确,因为有一件事情应该按升序排序(在STL中说“严格的弱排序”)。
其次,你使用STL中作为树实现的“集合”,而不是作为链表的“列表”。随机插入集合比插入列表末尾更昂贵。
尝试在C ++示例中使用一个int列表,并首先对列表进行排序(否则设置inersection将无法正常工作),我认为您会看到更有利的结果。
答案 1 :(得分:5)
我在我的linux盒子上运行了你的C ++代码
$ time ./test
real 0m0.073s
user 0m0.060s
sys 0m0.003s
21s对我来说意味着你编译时没有优化。如果您使用MSVC,请确保已列出
编译定义中的_SECURE_SCL=0
(参见msdn)。否则所有STL迭代器操作都会变慢。
答案 2 :(得分:2)
在这个古老的3GHz Pentium 4上,我在整个runIntersectionTestAlgo
函数中得到2734毫秒,在调试版本中禁用了优化。我用VS2008 SP1编译。
如果我启用优化,我会得到93毫秒。
这是我的代码:
#include <set>
#include <algorithm>
using namespace std;
int runIntersectionTestAlgo()
{
set<int> set1;
set<int> set2;
set<int> intersection;
// Create 100,000 values for set1
for ( int i = 0; i < 100000; i++ )
{
int value = 1000000000 + i;
set1.insert(value);
}
// Create 1,000 values for set2
for ( int i = 0; i < 1000; i++ )
{
int random = rand() % 200000 + 1;
random *= 10;
int value = 1000000000 + random;
set2.insert(value);
}
set_intersection(set1.begin(),set1.end(), set2.begin(), set2.end(), inserter(intersection, intersection.end()));
return intersection.size();
}
#include <windows.h>
#include <iostream>
int main(){
DWORD start = GetTickCount();
runIntersectionTestAlgo();
DWORD span = GetTickCount() - start;
std::cout << span << " milliseconds\n";
}
禁用_SECURE_SCL
对于版本构建没有任何影响,它仍然在100毫秒左右徘徊。
GetTickCount
并不理想,但它应该足以区分21秒和不到100毫秒。
所以我得出结论,你的基准测试有问题。
答案 3 :(得分:1)
我更新了您的示例以使用我在单元测试时使用的一些计时器代码。在我的机器上,我得到以下时间(基于-O3):
First loop 0.0040654
Second loop 4.8e-05
Intersection 0.000349
Intersection size: 50
基于此,如果我正确读取小数,则将项目插入第一组需要“4ms”,将项目插入第二组需要50微秒,执行1/3 ms十字路口。
我无法在我的机器上运行你的C#示例,所以我无法比较时间,但是你发布时绝对不是21秒。
答案 4 :(得分:0)
您的C#和C ++代码的工作方式不同。 C#代码使用神奇的散列技巧来提高速度,你的C ++代码使用树形技巧来提高速度。有一件事可能会加快速度(忽略你的测试似乎被打破的事实)将是使用散列,如下所示:
hash_map
。