Здравствуйте, Codealot, Вы писали:
C>Для тех же данных, код на C++ выполняется за 5.9 секунд и на C# за 1.2 секунды.
Сначала хотел сказать что выделение памяти, но теперь понятно что их нет. Возможно, в C# более быстрая версия парсера, а может цикл вообще параллелится. Нашёл вот это
P.S. Посмотри флаги ещё, должно быть -O3 и мб спец. оптимизации какие-то включить.
C> for (auto& cur : vals)
C> {
C> auto num = std::stoi(cur);
C> }
C>
C>
C> foreach (var val in vals)
C> {
C> var num = int.Parse(val);
C> _hash ^= num.GetHashCode();
C> }
C>
C>Для тех же данных, код на C++ выполняется за 5.9 секунд и на C# за 1.2 секунды. C>
Вообще, в таких случаях желательно видеть полные тексты примеров. Какие типы контейнеров и элементов, что и как меряешь и пр. И какую конфигурацию ты меряешь — не Debug, случайно?
На моем ноуте картина получается прямо противоположная: на выборке в 10 миллионов элементов: C++ — 150 ms, C# — 800 ms и более. Коды примеров ниже:
C++ (150 ms)
#include <iostream>
#include <vector>
#include <string>
#include <chrono>
std::vector<std::string> MakeIntSequence(int size)
{
std::vector<std::string> v;
v.reserve(size);
for (int i = 0; i < size; ++i)
{
v.push_back(std::to_string(i));
}
return v;
}
int main()
{
namespace tm = std::chrono;
const auto vals = MakeIntSequence(10000000);
const auto t0 = tm::steady_clock::now();
int hash{};
for (const auto& val : vals)
{
hash ^= atoi(val.c_str());
}
const auto dt = tm::duration_cast<tm::milliseconds>(tm::steady_clock::now() - t0);
std::cout << "Processing time: " << dt.count() << "ms" << std::endl;
}
C# (800 ms)
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
var vals = MakeIntSequence(10000000);
var t0 = DateTime.Now;
int hash = 0;
foreach (var val in vals)
{
int num = int.Parse(val);
hash ^= num.GetHashCode();
}
var dt = DateTime.Now - t0;
Console.WriteLine("Processing time: {0}ms", dt.TotalMilliseconds);
}
static List<string> MakeIntSequence(int size)
{
var vals = new List<string>(size);
for (int i = 0; i < size; ++i)
{
vals.Add(i.ToString());
}
return vals;
}
}
}
На бОльших выборках C# начинает колбасить не по-детски.
Здравствуйте, rg45, Вы писали:
R>И какую конфигурацию ты меряешь — не Debug, случайно?
Случайно нет.
R>На моем ноуте картина получается прямо противоположная: на выборке в 10 миллионов элементов: C++ — 150 ms, C# — 800 ms и более. Коды примеров ниже:
Ну начнем с того, что у тебя там string а не wstring. Так что ты сравниваешь яблоки с апельсинами.
Ад пуст, все бесы здесь.
Re[3]: [performance] чего-то я не понимаю в этой жизни
Здравствуйте, Nuzhny, Вы писали:
N>Так это твои проблемы, надо научиться корректно задавать вопросы
Я обычно предполагаю, что люди должны иметь хотя бы базовые знания, чтобы попытаться ответить. Знание того, что в C# все строки в юникоде и сравнивать анси с юникодом неправильно — это как раз из числа базовых знаний.
Ад пуст, все бесы здесь.
Re[2]: [performance] чего-то я не понимаю в этой жизни
Здравствуйте, Codealot, Вы писали:
R>>На моем ноуте картина получается прямо противоположная: на выборке в 10 миллионов элементов: C++ — 150 ms, C# — 800 ms и более. Коды примеров ниже:
C>Ну начнем с того, что у тебя там string а не wstring. Так что ты сравниваешь яблоки с апельсинами.
Разница по времени в конвертации строки в целое между ascii и wide-строк минимальна, но да, работа с wstring чуть-чуть медленнее, подозреваю из-за большего кол-ва (в 2 раза) памяти которую надо прочитать.
Re[3]: [performance] чего-то я не понимаю в этой жизни
Здравствуйте, Codealot, Вы писали: C>Ну начнем с того, что у тебя там string а не wstring. Так что ты сравниваешь яблоки с апельсинами.
Ok, мой косяк. С возрастом зрение слабеет, понимаешь, не разглядел, что у тебя stoi, показалось, что atoi.
Ну, давай исправим, какие проблемы:
C++ (290 ms)
#include <iostream>
#include <vector>
#include <string>
#include <chrono>
std::vector<std::wstring> MakeIntSequence(int size)
{
std::vector<std::wstring> v;
v.reserve(size);
for (int i = 0; i < size; ++i)
{
v.push_back(std::to_wstring(i));
}
return v;
}
int main()
{
namespace tm = std::chrono;
const auto vals = MakeIntSequence(10000000);
const auto t0 = tm::steady_clock::now();
int hash{};
for (const auto& val : vals)
{
hash ^= std::stoi(val);
}
const auto dt = tm::duration_cast<tm::milliseconds>(tm::steady_clock::now() - t0);
std::cout << "Processing time: " << dt.count() << "ms" << std::endl;
}
Все равно получается 300 против 800. Как ты умудрился получить плюсовый код в пять раз медленнее шарпного, по-прежнему остается загадкой. Моежт, приведешь уже полные тексты примеров?
--
Re[3]: [performance] чего-то я не понимаю в этой жизни
Здравствуйте, rg45, Вы писали:
R>Все равно получается 300 против 800. Как ты умудрился получить плюсовый код в пять раз медленнее шарпного, по-прежнему остается загадкой. Моежт, приведешь уже полные тексты примеров?
Я подозреваю, что у него там не обычный С++, а дотнетовский. И это мы сами должны были догадаться.
Re[5]: [performance] чего-то я не понимаю в этой жизни
, VS 2017, /O2, разница в пользу C++ конечно не в 5 раз, но где-то +- в 2.5 раза если использовать C-шые atoi/wcstol, и где-то в 2 раза если юзать C++ std::stoi — это если сравнивать с .NET "старого" framework, до версии 4.8.
Для .NET v5 vs C++ — C++ проигрывает с результатом — в 2.3 раза если юзать C++ std::stoi, и в 1.5 раза если использовать C-шые atoi/wcstol, но выигрывает у .NET5 в 2.8 раз если использовать std::from_chars, правда только для ascii, для wchar_t реализации нет.
с опцией /clr:pure разница от чисто нативного минимальна (даже чуть быстрей ), подозреваю что самого IL кода генерится мало, цикл по сути, а реализация atoi И проч. нативная.