Итак, несколько лет назад я написал программу на Python, которая записывает английские имена последовательного списка чисел в файл (один, два, три и т. д.). Я работал над тем, чтобы версия C++ работала в течение последнего месяца (личный проект), и я думаю, что она у меня работает довольно хорошо. Одна проблема: это в пять раз медленнее, чем версия Python. Я пробовал переключать методы конкатенации строк (<<
vs operator+
vs operator+=
vs .append()
), используя fprinf()
вместо ofstream
, предварительно выделяя размер строки (.reserve()
) и многое другое, что я не могу вспомнить, но, похоже, врезались в стену. Затем я заметил, что скорость записи C++, кажется, составляет около 70 МБ / с, тогда как версия Python записывает около 350 МБ / с. Я использую диск со скоростью вращения 5400 об / мин (CrystalDiskMark дает скорость последовательной записи 60-90 МБ / с), так что скорости записи C++ правдоподобны, но Python?
TL; DR: Кажется, Python пишет в пять раз быстрее, чем возможно (почти со скоростью чтения!) С диска.
Я включил программы ниже, на случай, если мне не хватает чего-то очевидного (правдоподобного). «Бенчмаркинг» включал запуск каждой программы для чисел 1–1 000 000, в результате чего получился файл размером 50 824 КБ. ~ 50 с для C++, ~ 8,5 с для Python.
##Code in Python version 2.7.5 for generating a file with the English names of a set range of numbers.
while 1:
s=input("Starting_Value:")
f=input("Ending_Value:")
filename=raw_input("Desired Name of File:")
##dictionary
one=["","one","two","three","four","five","six","seven","eight","nine","error_one"]
one2=["","-one","-two","-three","-four","-five","-six","-seven","-eight","-nine","error_one2"]
teen=["ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","error_teen"]
ten=["","twenty","thirty","fourty","fifty","sixty","seventy","eighty","ninety","error_ten"]
##Functions
def translate(n): ##handles '' to 999
work=[]
if n>=100:
work.append(one[int(n/100)]+" hundred ")
n=n-(100*int(n/100))
if n>=10:
if n>=20:
work.append(ten[int(n/10)-1]+one2[n-(10*int(n/10))]+" ")
else:
work.append(teen[n%10]+" ")
elif n>=1:
work.append(one[n]+ " ")
elif n>=10:
if n>=20:
work.append(ten[int(n/10)-1]+one2[n-(10*int(n/10))]+" ")
else:
work.append(teen[n%10]+" ")
elif n>=1:
work.append(str(one[n])+" ")
end1=', '.join(work)
end1=end1.replace(", ","")
return end1
def english(m): ##handles billions, hundred millions, millions, hundred thousands, thousands
work2=[]
if m>=1000000000:
work2.append(str(translate(int(m/1000000000)))+"billion ")
elif m>=1000000:
work2.append(str(translate(int(m/1000000)))+"million "+str(translate(int(m-(1000000*int(m/1000000)))/1000))+"thousand "+str(translate(m-(1000*int(m/1000)))))
if ((int(m/1000)%1000)==0):
end3=str(', '.join(work2))
end4=end3.replace("thousand ", "")
work2[:]=[]
work2=[str(end4)]
else:
end3=str()
elif m>=1000:
work2.append(str(translate(int(m/1000)))+"thousand "+str(translate(m%1000)))
elif m>=1:
work2.append(translate(m))
end2=str(', '.join(work2))
end2=end2[:-1]
return end2
##Main Program - Iterator
file = open(str(filename), "a")
for i in range(f-s+1):
file.write(str(english(s))+", ")
s = s + 1
file.close()
a = raw_input("Close window to EXIT, or press ENTER to generate another file")
//Generates a file of sequential numbers in English
//libraries
#include <iostream> //for output to terminal
#include <fstream> //for output to file
#include <string> //for handling strings
using namespace std; //yes
ofstream fout; //for convenience with 'cout'
//function prototypes
string thousands(int n); //translates 1 to 999
string millions(int m); //translates the hundred thousands, millions,
hundred millions
int lint(int j, int k); //outputs the digits of a number greater than the kth place i.e. lint(123456, 1000) = 123
//variables
int shi = 0; //starting value
int kut = 1; //ending value
int i = 0; //iterator
string fname = ""; //filename
string buffern = ""; //buffer for thousands
string bufferm = ""; //buffer for millions
string bufferf = ""; //first digit buffer
//dictionary
char one[10][7] = { ""," one"," two"," three"," four"," five"," six"," seven"," eight"," nine" };
char one2[10][7] = { "","-one","-two","-three","-four","-five","-six","-seven","-eight","-nine" };
char teen[10][11] = { " ten"," eleven"," twelve"," thirteen"," fourteen"," fifteen"," sixteen"," seventeen"," eighteen"," nineteen" };
char ten[10][9] = { "",""," twenty"," thirty"," fourty"," fifty"," sixty"," seventy"," eighty"," ninety" };
//main function
int main()
{
while (1)
{
//get user input
cout << " Starting Number: ";
cin >> shi;
cout << " Ending Number: ";
cin >> kut;
while (fout.is_open() != 1)
{
cout << " Desired Filename: ";
cin >> fname;
fname.append(".txt");
fout.open(fname);
if (fout.is_open() != 1)
cout << "\n Invalid file name. Please try again.\n";
}
//translate and write to file
if (shi == 0) { //handles starting at zero
fout << "zero,";
shi = 1;
}
else //handles spacing for next word
{
bufferf = millions(shi);
bufferf.erase(0, 1);
bufferf += ",";
fout << bufferf;
shi++;
}
for (i = shi; i < (kut); ++i) //Main Iterator
{
fout << millions(i) << ",";
}
fout << millions(kut) << "."; //handles last word
fout.close();
//display confirmation and prompt to exit/continue
cout << "\n Complete\n";
cin.get();
cin.ignore();
cout << endl;
}
}
//function definitions
string thousands(int n) //writes '' to 999
{
buffern = "";
buffern.reserve(30);
if (n >= 100) { //write hundreds place
buffern += one[lint(n, 100)];
buffern += " hundred";
n = n % 100;
if (n >= 10) { //write tens place
if (n >= 20) {
buffern += ten[lint(n, 10)];
buffern += one2[n % 10];
}
else { //deal with 'teens'
buffern += teen[n % 10];
}
}
else if (n >= 1) { //write ones place
buffern += one[n % 10];
}
}
else if (n >= 10) { //write tens place
if (n >= 20) {
buffern += ten[lint(n, 10)];
buffern += one2[n % 10];
}
else { //deal with 'teens'
buffern += teen[n % 10];
}
}
else if (n >= 1) { //write ones place
buffern += one[n];
}
return buffern;
}
string millions(int m)
{
bufferm = "";
bufferm.reserve(100);
if (m >= 1000000)
{
if (int(m / 1000) % 1000 == 0) { //if xxx,000,xxx
bufferm += thousands(lint(m, 1000000));
bufferm += " million";
bufferm += thousands(m % 1000);
}
else {
bufferm += thousands(lint(m, 1000000)); //millions
bufferm += " million";
bufferm += thousands(lint(m, 1000) % 1000); //hundred thousands
bufferm += " thousand";
bufferm += thousands(m % 1000); //thousands
}
}
else if (m >= 1000) {
bufferm += thousands(lint(m, 1000)); //hundred thousands
bufferm += " thousand";
bufferm += thousands(m % 1000); //thousands
}
else if (m >= 1) {
bufferm += thousands(m); //thousands
}
return bufferm;
}
int lint(int j, int k)
{
return ((j - (j % k)) / k);
}
Я был бы признателен за любое понимание того, почему программы работают с разной скоростью, как Python пишет так быстро, или предложения по ускорению кода C++.
Редактировать: @VTT был прав, там был не весь код C++. Добавлен.
Несвязанный. В этом коде C++ много глобальных переменных. Держу пари, они тебе не нужны.
Более полезно то, что ваша среда разработки может поставляться с программным обеспечением для профилирования. Запустите его и посмотрите, что съедает все ваше время.
@VTT Хорошо, оптимизация не была включена ... C++ теперь работает практически с той же скоростью, что и Python. Спасибо! Все еще не уверен, почему он может писать так быстро ... Может ли это быть из-за того, что серийная скорость намного выше, чем измеряет CrystalDisk?
@IronEagle: Операционные системы (и даже библиотеки) выполняют кэширование / буферизацию. Поскольку вы не сбрасываете / не синхронизируете изменения на диске, вы на самом деле не ждете / не измеряете время, необходимое для фактической записи данных на диск - вот почему вы видите скорость выше, чем ваш диск.
@Acorn: не считая того, что передачи могут происходить по DMA.
Оба будут использовать один и тот же API ввода-вывода, предоставляемый операционной системой. Так что разница в производительности может возникнуть только из-за этого причудливого словесного кода. Также обычный вопрос: включали ли вы оптимизацию при компиляции кода на C++? А реализация на C++ кажется неполной, например нет функции
millions
.