Automatik Pemberitahuan Dalam C + + Loops

6 Komen
Dihantar 26 Februari 2009 di Perangkat Lunak . Tag: , .

Sebagai seorang ahli fizik pengkomputeran, aku sering menjalankan program-program yang terdiri daripada pelbagai bersarang untuk-loops . Pada saat ini, kitaran loop terluar saya melalui berjuta-juta titik data dan loop dalam mengeksplorasi berbagai puluhan ribu parameter. Aku selalu mengutak-atik tatacara pada loop bahagian dalam cara-cara yang menyebabkan masa lari ke bervariasi antara 10 saat dan 10 minggu.

Mengganggu, itu tidak selalu mudah untuk menganggarkan berapa lama program ini akan berjalan selepas setiap rangkaian pengubahsuaian. Selain itu, kod saya kadang-kadang memiliki bug yang membuat menggantung tanpa batas. Ketika waktu diharapkan menjalankan program adalah diukur dalam minggu, itu menenteramkan untuk melihat laporan kemajuan secara teratur. Kalau tidak, aku bimbang bahawa program ini telah diam-diam jatuh.

Pada awalnya saya hanya menampar kenyataan cetak ke terluar untuk loop, terbungkus dalam jika-maka kenyataan yang hanya dihidupkan selepas setiap 1000 loop. Kenyataan cetak menggunakan waktu yang telah berlalu sejak awal loop dan kemajuan yang sudah semua untuk menganggarkan waktu yang tersisa. Ia tampak sedikit seperti ini (ditambah beberapa taip casting ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
( NULL ) ; //Grab starting time. = Waktu start_time (NULL); / / Muat masa bermula.
i = 0 ; i < i_end ; i ++ ) { for (i = 0; i_end <i; i + +) (
i + 1 ) % 1000 == 0 ) { //Only print every 1000 loops. if ((i + 1)% 1000 == 0) (/ / Hanya mencetak setiap 1000 loop.
( NULL ) ; //Grab current time. current_time = time (NULL); / / Muat waktu saat ini.
start_time ; timespan - = current_time start_time;
/ / Waktu TOTAL untuk penyelesaian boleh diperolehi dengan
/ Membagi timespan / oleh fraksi sudah dilakukan.
/ / Setelah mengurangkan timespan, sisa waktu
/ / Yang tersisa (di saat, yang sering membingungkan).
( i + 1 ) / ( i_end + 1 ) - timespan ; time_remaining = timespan / (i + 1) / (i_end + 1) - timespan;
( i + 1 ) / i_end * 100 << "% finished, " cout <<(i + 1) / i_end * 100 <<"% selesai,"
"seconds remaining." << endl ; <<Time_remaining <<"detik yang tersisa <." <Endl;
)

j = 0 ; j < j_end ; j ++ ) { for (j = 0; j <j_end; j + +) (
/ / Adakah banyak barang di sini.
)
)

Ini cukup sampai aku berubah dengan tatacara dari loop batin dengan cara yang meningkat ketika dijalankan secara dramatik. Notis pertama memuat jam untuk muncul, yang saya anggap tidak dapat diterima lambat. Lalu aku cuba membuat laporan mengaktifkan cetak setiap 10 loop untuk mempercepatkan pemberitahuan apabila waktu berjalan sangat lama, tapi yang memenuhi fail log dengan Mb laporan cetak dan melambatkan program. Ini menjadi jelas bahawa hacks cepat akan memerlukan lebih banyak penjagaan yang berterusan. Saya memerlukan sistem notis yang secara automatik dapat menyesuaikan diri dengan jangka masa panjang dan pendek.

Solusi saya sebut saya "Automatik Pemberitahuan". Versi terbaru adalah v1.2, yang dapat didownload di sini .

Ciri-ciri:

  • Waktu sampai notis pertama kali muncul boleh dikawal secara berasingan dari pemberitahuan yang lain, dan lalai untuk 10 saat.
  • Jumlah masa antara semua notis selanjutnya dikawal oleh variabel yang menentukan interval sasaran antara notis. Interval yang sebenarnya akan berada dalam jarak 30% daripada sasaran (5 minit default).
  • Sejumlah minimum (default 4) notis akan dicetak oleh notify (). Ini hanya mengaktifkan jika run time diproyeksikan kurang dari interval dipilih antara notis.
  • Waktu yang tersisa dicetak dalam format terbaca-manusia menggunakan seconds_to_string () fungsi. Waktu adalah dilaporkan dalam tahun, minggu, hari, jam, minit, saat. Tidak lebih dari 2 unit akan dicetak dalam setiap kenyataan untuk mengurangkan kekacauan (walaupun nilai ini dapat disesuaikan).
  • Sebuah kenyataan mencetak laporan waktu yang telah berlalu pada akhir loop, sehingga estimasi waktu yang tersisa dapat undian terhadap berapa lama sebenarnya memuat loop.
  • Lingkaran luar boleh mula kapan saja (positif! - Harus memperbaiki ini!) Indeks, tidak hanya 0 seperti pada contoh di atas.
  • Pilihan pemberitahuan Kebanyakan ditetapkan di atas masing-masing loop, loop sehingga beberapa boleh dikonfigurasikan berbeza (custom_example.cpp lihat).
  • Ini mungkin idea yang baik untuk meletakkan kod ke dalam fungsi notis bahawa menyimpan data ke disk sehingga jika komputer crash atau kuasa padam, aplikasi boleh bermula kembali dari titik notis terkini. Variabel notification.partial_saves_enabled bertujuan untuk menghidupkan kod ini tidak tertulis, tetapi anda juga harus lulus hujah baru untuk memberitahu () fungsi yang mengandungi data yang ingin ditulis ke cakera.

Syarat:

  • Dimaksudkan untuk digunakan dalam program C + +, diuji dengan menggunakan g + + compiler yang datang dengan Ubuntu 8.10 64-bit .
  • loop terluar anda harus kitaran atas indeks banyak (puluhan atau lebih). loop boleh mula setiap indeks yang anda inginkan, tapi perlu naik 1 di masing-masing loop.
  • Memerlukan iostream itu, iomanip dan perpustakaan vektor (sedia di Ubuntu secara default).

Program ini dibahagi menjadi 3 file: common_declarations.hpp mengandungi definisi dan deklarasi datatype fungsi, common_functions.cpp mempunyai definisi fungsi untuk memberitahu () dan sec2human () ketika example.cpp hanya sebuah loop contoh yang menggunakan Notis Automatik.

Divisi ini tidak diperlukan, tetapi saya telah menemui itu cara yang baik untuk menetapkan projek perisian yang lebih besar. Dengan cara ini, banyak digunakan fungsi yang jarang berubah boleh diisytiharkan dan ditakrifkan dalam fail yang sama dan disusun secara berasingan dari program-program yang hanya menggunakan fungsi-fungsi.

Makefile disertakan dengan Automatik Pemberitahuan mengkompilasi dalam dua langkah untuk menggambarkan teknik ini. Setelah menambah banyak fungsi versi saya dari gambar-gambar yang sama, langkah kompilasi pertama kali hampir satu jam di komputer saya. Langkah ini hanya terjadi ketika jumlah gambar umum adalah disunting, Namun, yang bermaksud jarang diperlukan. Langkah kompilasi kedua, di sisi lain, adalah lebih kerap dan lebih cepat.

By the way, common_declarations.hpp mengandungi baris "menggunakan namespace std". Saya telah membaca bahawa ini adalah amalan pengaturcaraan yang buruk, tapi aku belum bertemu konsekuensi serius belum, dan nyaman tidak harus menaip "std::" setiap kali saya hendak menggunakan "mahkamah".

Inilah yang example.cpp seperti:

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
/************************************************* *******
Tujuan:
Program ini menjalankan sebuah set loop bersarang yang
berguna untuk melakukan beberapa perhitungan
minit (waktu yang tepat bergantung pada kelajuan
Anda komputer dan batas-batas nested
loop). Ini bertujuan untuk menunjukkan
memberitahu () function.
************************************************** *******
Ditulis oleh Dumb Scientific
Pertama ditulis: 2009/02/26
Diubah buat kali terakhir: 2009/03/08
************************************************** ******/

/ / Header file "common_declarations.hpp" banyak firman
/ / Fungsi, pemalar dan datatypes. Untuk menggunakan
/ / Fungsi dideklarasikan di dalamnya, anda perlu menggunakan program ini
/ / Dengan kod objek dibuat dengan menggunakan common_functions.cpp.
# Include "common_declarations.hpp"

int main () (

/ / Deklarasi counter dan batas loop.
0 ,i,j,i_start = 30 ,i_end = 200000 ,j_end = 200000 ; sementara panjang = 0, i, j, i_start = 30, i_end = 200,000, j_end = 200,000;

/ / Inisialisasi variable untuk memberitahu ().
notification_struct notis;
/ / Tukar ini string untuk apa pun yang anda inginkan.
"Example loop" ; notis =. awalan Contoh loop "";
/ / Indeks awal anda mungkin akan berbeza.
i_start ; notis =. starting_index i_start;
/ / Indeks akhir Anda juga akan cenderung berbeza.
i_end - notification. starting_index ; . I_end num_loops = notis - notis. Starting_index;

i = notification. starting_index ; i < i_end ; i ++ ) { for (i = notis;. starting_index i_end <i; i + +) (
/ / Cetak berkala waktu yang tersisa.
; memberitahu (notis, i);

j = 0 ; j < j_end ; j ++ ) { for (j = 0; j <j_end; j + +) (
/ Sepenuhnya perhitungan kepada /.
( i * j * j * j - 2 * i + 3 * j ) ; temp + = (i * j * j * j - 2 * i + 3 * j);
) / / Akhir loop batin.
) / / Akhir dari luar loop.

/ / Rakam waktu akhir program.
time ( NULL ) ; notis =. end_time masa (NULL);
notification. end_time - notification. start_time ; notis. time_total = notis -. end_time notis. start_time;
notification. prefix << " took " cout <<notis. awalan <<"memuat"
notification. time_total ) << endl ; <<Seconds_to_string (notification. time_total) <<endl;

/ / Jika temp tidak digunakan di suatu tempat, program ini memerlukan
/ / 0 saat. Saya pikir itu keputusan-O2
/ / Bendera menyedari bahawa loop di atas tidak diperlukan.
return temp;
)

Ketika dijalankan, menghasilkan output yang kelihatan seperti ini diketahui (bahawa baris pertama kali muncul dalam hitungan detik, dan notis selanjutnya adalah 25% selain karena waktu menjalankan program ini dianggarkan kurang dari interval default):

1
2
3
4
5
6
loop Contoh adalah di 8,20%. Sisa waktu: 1 minit, 52 saat
Contoh loop berada di 33,20%. Sisa waktu: 1 minit, 20 saat
Contoh loop berada di 58,19%. Waktu yang tersisa: 51 saat
loop Contoh berada pada 83,19%. Waktu yang tersisa: 20 saat
loop Contoh masa 2 minit, 1 saat
`

Saya menukar batas-batas loop dengan menambah 4 masing-masing sifar i_end dan j_end, tapi baris pertama masih muncul dalam saat:

1
2
loop Contoh adalah pada 0,00%. Waktu yang tersisa: 285 tahun, 10 minggu
`

Jelas, aku tidak menunggu untuk yang pertama untuk menyelesaikan. Tetapi intinya adalah bahawa saya cepat tahu aku akan mati kerana usia tua berabad-abad sebelum itu. Kebetulan, aku cuba menambah beberapa nombor sifar j_end dan menyebabkan notis pertama untuk mengambil masa menjengkelkan lama untuk muncul. Hal ini terjadi kerana loop luar memakan masa lama untuk kenaikan hanya sekali. Aku belum yakin bagaimana saya ingin mengatasi masalah ini.

Pemberitahuan automatik adalah perisian bebas, berlesen di bawah GPLv3 daripada lesen CC bahawa sisa laman web ini menggunakan. Jika notis ada bugs atau mempunyai cadangan untuk Notis bagaimana meningkatkan Automatik, sila beritahu saya di komentar di bawah ini. Saya juga penasaran ingin melihat bagaimana orang lain telah menyelesaikan masalah ini, terlepas dari bahasa yang ditulis masuk

Versi Sejarah

v1.2 - 2009/03/08 - Sederhana tetapan lalai untuk memendekkan example.cpp, tambah custom_example.cpp.

v1.1 - 2009/02/27 - max Diganti dan interval minit dengan target_interval.

v1.0 - 2009/02/26 - Original keluaran.

Diubah buat kali terakhir 2 Ogos 2009
.
Berkongsi Perkara ini Subscribe to Articles Feed Feed Artikel Subscribe to Comments Feed Feed Ulasan
.

6 Responses to "Notis Automatik Dalam C + + Loops"

  1. Anonymous diposting pada 2009/09/20 pada 03:16

    Aku heran kau tidak menggunakan pemasa interrupt. Tidak ada overhead sementara loop berjalan dan kawalan tepat interval sampel. Hanya perlu beberapa cara untuk mendapatkan variable loop ke interrupt handler dan hasil keluar.

    • Apakah tidak menggunakan itu karena aku belum pernah mendengar hal itu sebelumnya. Terima kasih, saya akan melihat ke dalamnya.

    • Produksi "" versi fungsi ini menerima struktur dengan beberapa GB data dan autosaves it to disk. Aku bertanya-tanya apakah pemasa interrupt boleh dihantar bahawa banyak data secara telus? Iaitu keseluruhan struktur perlu dihantar melalui rujukan sebagai hujah tunggal tanpa membuat copy tempatan dari data (hampir tidak berpadanan menjadi memori sudah.)

      Selain itu, fungsi perlu disebut pada tempat tepat dalam kod, tidak di dalam loop dalam, dinyatakan fungsi autosave tidak akan berfungsi dengan betul. Jika semua ini dimungkinkan dengan pemasa mengganggu, seseorang sila titik saya untuk beberapa kod contoh.

  2. (Ed. nota: komen ini pada asalnya diposting di sini .)

    Menjaga hal-hal dalam fail berasingan dan termasuk mereka adalah teknik organisasi yang baik ...

    Mengapa? Itu hanya bererti aku harus membuka fail lebih ketika saya ingin melakukan penyelenggaraan banyak program.

    Kompilasi pasti lebih cepat jika anda hanya menggantikan 1 dari 100 gambar-gambar yang berukuran sama, tapi aku telah memilih untuk membuat dua fail sumber utama: yang pertama adalah jarang diedit dan besar (30k garis), sedangkan yang kedua diedit puluhan kali sehari dan hanya mempunyai 1k baris. Makefile mengkompilasi fail besar ke dalam kod objek yang kemudian dikaitkan dengan kod objek dari fail kecil. Fail besar hanya selepas dikompilasi jika tarikh semakan dari fail sumber besar lebih baru dari fail objek besar. Bahkan kompilasi kali untuk fail besar hanya ~ 10 minit pada netbook jika pengoptimuman dimatikan, dan tidak jelas bahawa saya mengkompilasi kali akan tumbuh lebih cepat dari kelajuan CPU akan. (Terutama jika selari g + + pernah mendapat yang layak.)

    Saya kira boleh dikatakan bahawa segmentasi kod membantu untuk menegakkan "beberapa interkoneksi antara fungsi" prinsip. (Atau apa pun itu secara rasmi disebut-idea bahawa fungsi harus berinteraksi hanya dalam beberapa cara yang jelas) yang ideal secara teori ini menarik., Tetapi nampaknya mengganggu untuk melaksanakan tanpa membolehkan anda sesekali pengecualian. Saya tidak mahu menukar pedoman kepada menjadi undang-undang kaku yang mungkin hanya akan melambatkan saya.

    Saya juga menulis kod sendiri, jadi alasan melibatkan pasukan pengaturcaraan tidak benar-benar relevan. Sebuah sistem kawalan versi yang baik seperti Mercurial harus meminimumkan isu-isu ini pula.

    Apakah ada produktiviti (nyata iaitu, skalabilitas) alasan untuk meninggalkan pendekatan ini dan mula menempatkan fungsi baru di file berasingan? Saya bukan programmer profesional, jadi aku mungkin telah melewatkan sesuatu yang PhD sains komputer akan mempertimbangkan jelas dan menarik ...

    • Anonymous diposting pada 2010/04/04 pada 09:32

      Saya juga menulis kod sendiri, jadi alasan melibatkan pasukan pengaturcaraan tidak benar-benar relevan

      Kerana anda kod anda di bawah lesen GPL (sehingga pada dasarnya anda menerima atau setidaknya tidak keberatan orang lain untuk belajar dan berkongsi kod anda), maka pengurusan kod adalah baik untuk memiliki yang boleh dicapai dengan modularitas .

      Yang paling penting untuk diingat adalah untuk memisahkan kod anda sesuai dengan apa yang dilakukannya (pemisahan logik). Terus terang saya belum melihat kod anda jadi mungkin tidak berlaku dalam hal ini (mungkin satu jumlah gambar benar-benar besar dibenarkan).

      Oleh itu, pada akhir hari tidak ada undang-undang yang kaku, hanya pedoman yang dibuat dari pengalaman dan banyak kesalahan:)

Tinggalkan Balasan

Komentar di DH4 tingkat atau lebih tinggi dihargai.

Anda boleh menggunakan tag HTML seperti <a <blockquote> href = ""> <strong> <code> dalam ulasan anda.

.
.