Я имел дело с некоторыми проблемами производительности, которые я обсуждал в этом вопросе: Super Slow C ++ For Loop
У меня есть простая программа, которую я написал для анализа двоичных данных. Я тестировал его локально на 2 компьютерах.
1. Dual 6 core 2.4GHz Xeon V3, 64GB RAM, NVMe SSD
2. Dual 4 core 3.5GHz Xeon V3, 64GB RAM, NVMe SSD
Вот часть кода (остальное на Wandbox https://wandbox.org/permlink/VIvardJNAMKzSbMf):
string HexRow="";
for (int i=b; i<HexLineLength+b;i++){
HexRow+= incomingData[i];
}
std::vector<unsigned char> BufferedLine=HexToBytes(HexRow);
stopwatch<> sw;
for (int i = 0; 80 >= i; ++i)
{
Byte ColumnBytes;
for (auto it = columns["data"][i].begin(); it != columns["data"][i].end(); ++it)
{
try {
if (it.key() == "Column") { ColumnBytes.Column = it.value().get<std::string>();}
else if (it.key() == "DataType") { ColumnBytes.DataType = it.value().get<std::string>();}
else if (it.key() == "StartingPosition") { ColumnBytes.StartingPosition = it.value().get<int>();}
else if (it.key() == "ColumnWidth") { ColumnBytes.ColumnWidth = it.value().get<int>();}
}
catch (...) {}
}
char* locale = setlocale(LC_ALL, "UTF-8");
std::vector<unsigned char> CurrentColumnBytes(ColumnBytes.ColumnWidth);
int arraySize = CurrentColumnBytes.size();
for (int C = ColumnBytes.StartingPosition; C < ColumnBytes.ColumnWidth + ColumnBytes.StartingPosition; ++C)
{
int Index = C - ColumnBytes.StartingPosition;
CurrentColumnBytes[Index] = BufferedLine[C-1];
}
}
std::cout << "Elapsed: " << duration_cast<double>(sw.elapsed()) << '\n';
ПК 1
Компиляция наПК 1 с Visual Studio с использованием следующих флагов:
/O2 /JMC /permissive- /MP /GS /analyze- /W3 /Zc:wchar_t /ZI /Gm- /sdl /Zc:inline /fp:precise /D "_CRT_SECURE_NO_WARNINGS" /D "_MBCS" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /MDd /std:c++17 /FC /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /Fp"Debug\Project1.pch" /diagnostics:column
Вывод:
Elapsed: 0.0913771
Elapsed: 0.0419886
Elapsed: 0.042406
Использование Clang со следующими параметрами: clang main.cpp -O3
вывод:
Elapsed: 0.036262
Elapsed: 0.0174264
Elapsed: 0.0170038
Компиляция с GCC из MinGW gcc version 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project)
с использованием этих переключателей gcc main.cpp -lstdc++ -O3
дает следующее время:
Elapsed: 0.019841
Elapsed: 0.0099643
Elapsed: 0.0094552
ПК 2
Я получаю с Visual Studio, все еще с / O2
Elapsed: 0.054841
Elapsed: 0.03543
Elapsed: 0.034552
Я не делал Clang и GCC на ПК 2, но улучшения не было достаточно значительным, чтобы решить мои проблемы.
Wandbox
Проблема в том, что точноетот же код на Wandbox (https://wandbox.org/permlink/VIvardJNAMKzSbMf) выполняется в 10-80 раз быстрее
Elapsed: 0.00115457
Elapsed: 0.000815412
Elapsed: 0.000814636
Wandbox использует GCC 10.0.0 и c ++ 14. Я понимаю, что он, вероятно, работает на Linux, и яНе удалось найти способ заставить GCC 10 компилироваться в Windows, поэтому я не могу проверить компиляцию с этой версией.
C # - 200X Faster
Этопереписать написанное мною приложение C #, которое работает намного быстрее:
Elapsed: 0.017424
Elapsed: 0.0006065
Elapsed: 0.000733
Elapsed: 0.0006166
Elapsed: 0.0004699
Finished Parsing: 100 Records. Elapsed :0.0082796 at a rate of : 12076/s
Метод C # выглядит следующим образом:
Stopwatch sw = new Stopwatch();
sw.Start();
foreach (dynamic item in TableData.data) //TableData is a JSON file with the structure definition
{
string DataType = item.DataType;
int startingPosition = item.StartingPosition;
int width = Convert.ToInt32(item.ColumnWidth);
if (width+startingPosition >= FullLineLength)
{
continue;
}
byte[] currentColumnBytes = currentLineBytes.Skip(startingPosition).Take(width).ToArray();
// ..... 200 extra lines of processing into ints, dates, strings ......
// ..... Even with the extra work, it operates at 1200+ records per second ......
}
sw.Stop();
var seconds = sw.Elapsed.TotalSeconds;
sw.Reset();
Console.WriteLine("Elapsed: " + seconds);
TempTable.Rows.Add(dataRow);
Когда я начал это, я ожидал огромного прироста производительностиперемещение кода в неуправляемый C ++ из C #. Это мой первый проект на C ++, и, честно говоря, я немного разочарован тем, где я нахожусь. Что можно сделать, чтобы ускорить этот C ++? Нужно ли использовать разные типы данных, malloc
, больше / меньше структур?
Он должен работать в Windows, не уверен, есть ли способ заставить GCC 10 работать в Windows?
Какие у вас есть предложения для начинающего разработчика C ++?