Като изчислителни физик, съм често изпълнявани програми, които се състоят от много вложени за-линии . В момента, моите най-отдалечените цикъла цикъла милиони данни точки и различни вътрешни линии опознаването на десетки хиляди параметри. Аз винаги съм си пилее времето с настройките на вътрешната петелки по начини, които причиняват навечерието време да варира между 10 секунди и 10 седмици.
Дразнещо, то не винаги е лесно да се предвиди колко време програмата ще продължи след всеки набор от модификации. Също така, ми код понякога има грешки, които правят го закачите за неопределено време. Когато се очаква пуснете програмата време се измерва в седмици, това е успокояващо, за да видите редовни доклади за напредъка. Иначе аз се тревожи, че програмата е тихо разбил.
Отначало просто плесна един печат изявление в най-отдалечените за цикъл, обвити в една -ако след това изявление, за което само активиран веднъж на всеки 1000 линии. За печат изявление използва времето, изминало от началото на цикъла и постигнатия напредък за оценка на оставащото време. Изглеждаше малко като това (плюс някои тип кастинг ):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ( NULL ) ; //Grab starting time. start_time = времето (NULL); / / Хвани начален час. i = 0 ; i < i_end ; i ++ ) { за (I = 0; I <i_end; I + +) ( i + 1 ) % 1000 == 0 ) { //Only print every 1000 loops. ако ((I + 1)% 1000 == 0) (/ / само за печат на всеки 1000 линии. ( NULL ) ; //Grab current time. current_time = времето (NULL); / / Хвани момента. start_time ; времеви диапазон = current_time - start_time; / / Общото време на проекта може да бъде получена от / / Разделяне времеви диапазон от фракция го направили. / / След като се извади времеви диапазон, в оставащото време / / Се оставя (в секунди, което често е объркваща). ( i + 1 ) / ( i_end + 1 ) - timespan ; time_remaining = времеви диапазон / (I + 1) / (i_end + 1) - времеви диапазон; ( i + 1 ) / i_end * 100 << "% finished, " Съдът <<(I + 1) / i_end * 100 <<"% завършен" "seconds remaining." << endl ; <<Time_remaining <<"секунди преди края." <<Endl; ) j = 0 ; j < j_end ; j ++ ) { за (J = 0; к <j_end; к + +) ( / / Да много неща тук. ) ) |
Това е достатъчно, докато не променят с настройките на вътрешните линии по начин, който увеличава тичам време драстично. В първото съобщение се час да се яви, което считам, неприемливо бавно. Тогава аз се опитах вземане на печат изявление активирате на всеки 10 линии за ускоряване на уведомлението, когато тече в момента е много дълъг, но напълно лог файл с мегабайта печат отчети и забави програмата. Стана ясно, че бързо хакове щеше да изисква много от текущата поддръжка. Имах нужда от система за уведомление, че да могат автоматично да се адаптират към близки и далечни времена план.
Аз наричам моето решение "Автоматизирани Известия". Последната версия е v1.2, която може да се изтегли от тук .
Удобства:
- Времето до първото уведомление изглежда може да се контролира отделно от другите уведомления, и по подразбиране е 10 секунди.
- Сумата от време между всички последващи уведомления са контролирани от една променлива, която определя целеви интервал между нотификации. Действителната интервали ще бъде в рамките на 30% от тази цел (пет минути по подразбиране).
- Минимален брой (по подразбиране е 4) на уведомления ще бъдат отпечатани и от уведомяват (). Това активира само ако очакваните тече в момента е по-малко от избрания интервал между нотификации.
- В оставащото време се отпечатва на един човек-четлив формат използва seconds_to_string () функция. Време е съобщено в години, седмици, дни, часове, минути, секунди. Не повече от 2 единици ще бъдат отпечатани във всеки отчет за намаляване на елементарно (въпреки че тази стойност е по избор).
- За печат изявление доклади времето, изтекло в края на цикъла, така че очакваните оставащото време може да се прецени с колко време действително се е линия.
- Външният контур може да започне по всяко (положителни! - Трябва да се определи това!) Индекс, а не само 0, както в примера по-горе.
- Повечето опции уведомление са посочени по-горе всяка линия, така че множество линии могат да бъдат конфигурирани по различен начин (вж. custom_example.cpp).
- Това е може би е добра идея да пуснат код в уведомлението функция, която спестява на данни на твърдия диск, така че ако компютърът блокира или от властта, излиза, заявката може да бъде рестартиран от последната точка уведомление. Променливата notification.partial_saves_enabled има за цел да се превърне по този неписан код, но вие също така ще трябва да премине нов аргумент в полза уведомяват () функция, съдържащ данните, които искате записва на диска.
Изисквания:
- Предназначени за използване в + + програми, C, изпитва с G + + компилатор, който идва с Ubuntu 8.10 64-битов .
- Вашият най-отдалечените линия трябва цикъл в продължение на много индекси (десетки или повече). В цикъл може да започне по всяко индекс, което искате, но е необходимо да се увеличат с 1 във всеки цикъл.
- Изисква от iostream, iomanip и библиотеки вектор (на Ubuntu по подразбиране).
Програмата е разделена на три файлове: common_declarations.hpp съдържа тип данни определена функция и декларации, common_functions.cpp е функция на дефинициите за уведомяват () и sec2human (), докато example.cpp е само един пример линия, която използва автоматизирана Известия.
Това разделение не е необходимо, но аз открих, че е един добър начин за организиране на големи софтуерни проекти. По този начин, широко използвани функции, които са рядко промяна може да бъде обявена и определени в общата файлове и изготвя отделно от програмите, които просто използват тези функции.
В Makefile включени с автоматизирана Известия съставя в две стъпки, за да илюстрират тази техника. След добавянето на много функции на моята версия на общите файлове, първата стъпка компилация отнема почти една минута на моя компютър. Тази стъпка се появява само когато общата файлове са редактирани, обаче, което означава, че това рядко е необходимо. Втората стъпка компилация, от друга страна, е по-често и много по-бързо.
Между другото, common_declarations.hpp съдържа реда "Именно чрез STD". Аз чета , че това е лошо програмиране практика, но аз не съм тичал в нито сериозни последствия още, и това не е удобно да трябва да въведете "STD::" Всеки път, когато искате да използвате "съд".
Ето какво example.cpp изглежда така:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | /************************************************* ******* Цел: Тази програма работи набор от вложени петелки, че изпълнява безполезна изчисления в продължение на няколко минути (точното време зависи от скоростта на вашия компютър и границите на вложените вериги). Това означава да се докаже уведомява () функция. ************************************************** ******* Написано от Глупаво учен Първо писмено: 02.26.2009 Последна промяна: 03.08.2009 ************************************************** ******/ / / Заглавен файл "common_declarations.hpp" декларира, много / / Функции, константи и типове данни. С цел да се използват / / Функции, декларирани в него, трябва да свърже тази програма / / С обектен код извършват common_functions.cpp. # Включват "common_declarations.hpp" INT главната () ( / / Обяви гишета и ограниченията за достъп. 0 ,i,j,i_start = 30 ,i_end = 200000 ,j_end = 200000 ; дълго Temp = 0, I, J, i_start = 30, i_end = 200000, j_end = 200000; / / Инициализира променлива за уведомяват (). notification_struct нотификация; / / Промяна този низ към всичко, което искаш. "Example loop" ; уведомление. префикс = "Пример линия"; / / Вашата начална индекса вероятно ще бъдат различни. i_start ; уведомление. starting_index = i_start; / / Вашият приключва индекс също ще бъдат различни. i_end - notification. starting_index ; уведомление. num_loops = i_end - уведомяване. starting_index; i = notification. starting_index ; i < i_end ; i ++ ) { за (I = уведомление. starting_index, аз <i_end; I + +) ( / / Периодично печат оставащото време. ; уведомява (нотификация, I); j = 0 ; j < j_end ; j ++ ) { за (J = 0; к <j_end; к + +) ( / / Напълно безполезен изчисление. ( i * j * j * j - 2 * i + 3 * j ) ; Temp + = (I * к * к * J - 2 * и 3 * + к); ) / / Край на вътрешната линия. ) / / Край на външната линия. / / За рекордно кратко време в края на програмата. time ( NULL ) ; уведомление. end_time = времето (NULL); notification. end_time - notification. start_time ; уведомление. time_total = уведомление. end_time - уведомяване. start_time; notification. prefix << " took " Съдът <<уведомление. префикс <<"се" notification. time_total ) << endl ; <<Seconds_to_string (notification. time_total) <<endl; / / Ако Temp не се използва някъде, тази програма се / / 0 секунди. Мисля, че това е резултат от най-O2 / / Флагът да забележи, че горните линии не са необходими. връщане Temp; ) |
Когато тече, тя произвежда продукция, която изглежда така (имайте предвид, че на първия ред се показва в секунди, а след уведомления са двайсет и пет процента освен поради очакваното време тече на тази програма е по-малък от този по подразбиране интервал):
1 2 3 4 5 6 | Пример линия е 8,20%. Оставащо време: 1 минута 52 секунди Пример линия е 33.20%. Оставащо време: 1 минута, 20секунди Пример линия е 58.19%. Оставащо време: 51 секунди Пример линия е 83.19%. Оставащо време: 20 секунди Пример линия се 2 минути, 1 секунда " |
Промених рамките на електрически вериги чрез добавяне на 4 нули всеки да i_end и j_end, но на първа линия още се появили в секунда:
1 2 | Пример линия е 0,00%. Оставащо време: 285 години, 10 седмици " |
Очевидно е, че аз не чакам за този един до край. Но въпросът е, че аз знаех, че скоро ще умре от старите векове възраст, преди да го е направил. Между другото, аз се опитах добавяне на още няколко нули към j_end и то му е причинило първото уведомление да вземат irritatingly дълго време да се появи. Това се случва, защото външната линия отнема много време, за да нарастване само веднъж. Аз не съм все още сигурен как искам да се реши този проблем.
Автоматизирани Известия е свободен софтуер, лицензиран под GPLv3 , а не на CC лиценза , че останалата част от сайта употреба. Ако някой известия всички грешки, или има някакви предложения за това как да се подобри автоматизирана Известия, моля да ме уведомите в коментарите по-долу. Аз също съм любопитен да видя как други са решили този проблем, независимо от езика е написан инча
Версия История
v1.2 - 08.03.2009 - опростен настройките по подразбиране за съкращаване example.cpp, допълни custom_example.cpp.
v1.1 - 27.02.2009 - Заменен макс и мин интервали с target_interval.
v1.0 - 26.02.2009 - оригиналната версия.
Обновен на 2-ри август 2009 год.

















































Аз съм изненадан, че не се е възползвал от таймер прекъсват. Не въздушната линия, докато работи и прецизен контрол на пробата интервал. Просто трябва някакъв начин, за да получите линия променливи в прекъсне треньор и резултатите от вън.
Не използвайте това, защото аз никога не съм го чувал и преди. Благодаря, ще го проучим.
"Производство" версия на тази функция приема структура с няколко GB данни и autosaves на диска. Аз съм се чудех дали един таймер прекъсване може да бъде изпратено, че много данни по прозрачен начин? Т.е. цялата структура трябва да бъде изпратена чрез контролни като един аргумент, без да прави локално копие на данните (то почти не се вписва в памет вече.)
Освен това, функцията трябва да бъде използван по това точното място в кода, а не във вътрешността на вътрешната линия, в противен случай Автоматичното функция няма да работи коректно. Ако всичко това е възможно с таймер прекъсва, някой да ми точка за някои пример код.
(Ed. Забележка: Този коментар е бил първоначално публикуван тук .)
Защо? Това просто означава, че трябва да започне по-файлове, когато искаш да изпълняват обширни поддръжка на програмата.
Изготвяне определено е по-бързо, ако единствената промяна, една от 100 Също размер файлове, но съм избрал да създаде два основни файлове източник: първата е рядко редактирани и големи (30k линии), а вторият се редактира десетки пъти на ден и има само 1k линии. В Makefile състав на големи файлове в обектен код, който след това се свързани с предмета кода от малък файл. Големият файл е съставен след това само ако преразглеждане датата на подаване на голям източник е по-нови от голям файл обект. Дори състав пъти за големи файлове са само ~ 10 секунди по Netbook ако оптимизация е забранено, и това не е ясно, че ми съставят пъти ще нарасне по-бързо от скоростта на процесора ще. (Особено ако паралелно G + + някога стане достоен.)
Предполагам, че човек може да се каже, че сегментиране код помага да се изпълни "няколко връзки между функции" принцип. (Или каквото и да е официално поискано идеята, че функцията трябва да проведе само няколко точно определени начини.) Този идеал е теоретично привлекателна, но изглежда досадно да приложи без да се позволява на случайни изключения. Аз не искам да се промени една полезна насока в твърдо законодателство, които вероятно ще просто ме забави.
Аз също писане на код от себе си, толкова причини, свързани със програмиране екипи не са наистина от значение. Една добра система за управление на версиите като живак трябва да сведе до минимум тези проблеми така или иначе.
Има ли някакви реални (т.е. производителност, скалируемост) причините да се откаже от този подход и да започне въвеждането на нови функции в отделни файлове? Аз не съм професионален програмист, така че може да сте пропуснали нещо, което компютърни науки р биха счели за очевидни и непреодолими ...
Тъй като позволително кодекс си под GPL (Така че основно сте добре дошли, или поне не се интересуваме от другите да учат и да споделят кода си), тогава управляемост код е хубаво да има, които могат да бъдат постигнати чрез модулността .
Най-важното нещо е да се раздели кода си според това, което го прави (логическо разделяне). За да бъда честен не съм разглеждал кода така че може би тя не се прилага в този случай (може би един действително голям файл е оправдано).
Като каза, че в края на деня не съществуват строги закони, само насоки, създадени от опит и много грешки:)
Отличен точки. Благодаря за статията.