所以,我有一种情况,我必须处理大型(多维)数组,只是想知道C#或C ++是否会表现更好。 (注意:我是C ++的初学者,所以不要过多地了解它是如何运作的!)。我认为在数组方面,两种语言的表现都差不多,也许C ++可能稍好一些但是:结果告诉其他故事:
1012ms in C++ @32Bit
1020ms in C++ @32Bit
1002ms in C++ @32Bit
1155ms in C++ @64Bit
1098ms in C++ @64Bit
1122ms in C++ @64Bit
1136ms in C++ @64Bit
523ms in C# @32-Bit
545ms in C# @32-Bit
537ms in C# @32-Bit
536ms in C# @32-Bit
473ms in C# @64-Bit
501ms in C# @64-Bit
470ms in C# @64-Bit
498ms in C# @64-Bit
我在x86执行了一次Test运行,在x64架构执行了一次。这里有两件事:为什么C#比C ++好几乎两倍?为什么C#在x64-Mode和x86-mode中的C ++实际上更快?!?我真的没想到会发生这种情况。
正如我所说,我目前没有C +经验 - 编程,但我尽力在C ++中复制我的C#-Code。
这里是代码: C#
for (int j = 0; j < 4; j++)
{
Stopwatch sw = new Stopwatch();
sw.Start();
struct1[] s1 = new struct1[20000000];
int length = 20000000;
for (int i = 0; i < length; i++)
{
s1[i] = new struct1();
s1[i].samplechar = 'c';
s1[i].sampleInt = i * 2;
s1[i].sampledouble = Math.Sqrt(i);
}
sw.Stop();
GC.Collect();
Console.WriteLine(sw.ElapsedMilliseconds + "ms in C# @...-Bit");
}
AND struct1:
public struct struct1
{
public int sampleInt;
public double sampledouble;
public char samplechar;
}
C ++:
for (int j = 0; j < 4; j++)
{
auto begin = std::chrono::high_resolution_clock::now();
struct1* s1 = new struct1[20000000];
int length = 20000000;
for (int i = 0; i < length; i++)
{
s1[i].sampleChar = 'c';
s1[i].sampleInt = i * 2;
s1[i].sampleDouble = sqrt(i);
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << "ms in C++ @64Bit" << std::endl;
free(s1);
}
struct1:
struct struct1 {
public:
int sampleInt;
int sampleDouble;
char sampleChar;
};
注意:我没有将垃圾收集/免费包含在性能测量中,因为 - 在我的情况下 - 只要程序运行,就会有一个巨大的数组存在。而且我认为很明显,除非你想杀死你的机器,否则会经常创建/删除这些大小的数组...
注2:另一个令人困惑的事情:虽然C ++消耗大约250MB的RAM,但C#需要500MB。但为什么呢?
提前感谢任何解释。也许我只是弄错了,失败只是坐在显示器后面,但我虽然对我为何得到这些结果感兴趣。
编辑:我在Windows 10上运行Visual Studio 2017RC。禁用C ++优化(/ Od)
答案 0 :(得分:0)
使用正确的优化和编译器设置,C ++版本应该至少与C#版本一样快。请注意,您没有完全相同地计算时间(看看您是否可以在C ++中使用StopWatch
进行尝试?) - 请参阅此问题以获取更多详细信息:resolution of std::chrono::high_resolution_clock doesn't correspond to measurements - 这是很可能是你不同时间的来源(特别是为什么C ++实现的测量时间更长)。 StopWatch
比您在std::chrono::high_resolution_clock
的VisualStudio / Windows实现中使用的更准确。
还要记住,你实际上并没有处理多维数组(例如C#中的int[,]
) - 你只是在处理一组结构。对于它的价值,我的回忆是实际多维数组的CLR实现并不是为大型集合的性能而构建的 - 它可能构建一个更快的(如果实际上你需要多维数组而不仅仅是结构数组) )。
这里更大的优势可能是能够更严格地控制内存管理 - 如果你正在分配大型结构数组,你可以使用C或C ++更密切地控制分配的生命周期。垃圾收集环境。您也可以更轻松/自然地使用指针算法和内存复制 - 尽管这在C#中的unsafe
上下文中也是完全可能的。与safe
上下文中的“vanilla”C#实现相比,可能会带来一些速度性能提升。
答案 1 :(得分:0)
除了Dan Field的回答:
注2:另一个令人困惑的事情:虽然C ++消耗大约250MB的RAM, C#需要500MB。但为什么呢?
在C ++中,你使用int,int,char
(至少在32位系统上)将填充到4,4,4字节(除非结构的打包设置为1字节)。
在C#中,你使用int,double,char
,它将被填充到8,8,8(或者4?)字节。填充第一个int以对齐8个字节的double。如果使用double,int,char
,结构应该更小(可能是16个字节)。
虽然我不是C#专家,但我不明白为什么你在循环中使用s1[i] = new struct1();
而已经有struct1
的文件? (但我可能错了或遗漏了什么)。
此外,在测试数组性能时,我不会在循环中使用sqrt()
,因为该函数比循环遍历项目更昂贵。
当然,在测试性能时应该启用优化。
使用循环注册甚至可以更快:
for (int i = 0; i < length; i+=4)
{
s1[i].sampleInt = i * 2;
s1[i].sampleDouble = i * 4;
s1[i].sampleChar = 'c'; // reordered in order of struct
// not sure if it matters
s1[i+1].sampleInt = (i+1) * 2;
s1[i+1].sampleDouble = (i+1) * 4;
s1[i+1].sampleChar = 'c';
// maybe 2 or 3 would be better than 4
s1[i+2].sampleInt = (i+2) * 2;
s1[i+2].sampleDouble = (i+2) * 4;
s1[i+2].sampleChar = 'c';
s1[i+3].sampleInt = (i+3) * 2;
s1[i+3].sampleDouble = (i+3) * 4;
s1[i+3].sampleChar = 'c';
}
与
相比for (int i = 0; i < length; i++)
{
s1[i].sampleChar = 'c';
s1[i].sampleInt = i * 2;
s1[i].sampleDouble = i * 4;
}