Apakah ada kekurangan dalam mengalokasikan sejumlah besar tumpukan untuk satu array dalam sistem tertanam?

12

Saya biasanya tidak punya masalah memutuskan apakah beberapa data harus bersifat global, statis atau di stack (Tidak ada alokasi dinamis di sini, jadi tidak ada gunanya tumpukan). Saya juga telah membaca beberapa T / A seperti ini tetapi pertanyaan saya lebih spesifik karena melibatkan sejumlah besar data, sangat besar dibandingkan dengan memori sistem.

Saya sedang mengerjakan kode yang sudah ada yang saya coba tingkatkan (desain, kemungkinan masalah, kinerja, dll.). Kode ini berjalan pada MCU 8bit lama dengan hanya 4KB RAM . Dalam kode ini saya menghadapi penggunaan array hampir 1KB (ya, 1KB pada sistem RAM 4KB ). Setiap byte array ini digunakan, bukan itu pertanyaannya. Masalahnya adalah array ini adalah array statis dalam file yang dideklarasikan, sehingga siklus hidupnya sama dengan program (yaitu dapat dianggap tak terbatas).

Namun, setelah membaca kode, saya baru tahu bahwa array ini tidak memerlukan siklus hidup yang tak terbatas, itu dibangun dan ditangani dengan cara yang sepenuhnya prosedural, jadi kita harus dapat mendeklarasikannya hanya dalam fungsi di mana ia digunakan, dengan cara ini akan berada di stack, dan karena itu kami akan menghemat 1KB RAM ini.

Sekarang pertanyaannya: Apakah ini ide yang bagus? Dari sudut pandang desain, jika tidak memerlukan siklus hidup tak terbatas / global, itu milik stack. Tapi hei, itu 1KB dari 4KB, tidak ada kekurangan mengalokasikan 25% dari RAM seperti ini? (itu mungkin 50% atau lebih dari tumpukan)

Bisakah seseorang berbagi pengalaman dengan situasi seperti ini, atau apakah seseorang memikirkan alasan yang sah untuk tidak meletakkan array ini di stack? Saya mencari kelemahan teknis serta komentar pada desain.

Satu-satunya hal yang saya sadari adalah saya harus memastikan bahwa saya benar-benar memiliki 1KB stack gratis ketika memasuki fungsi ini. Mungkin hanya itu yang harus saya selesaikan, mungkin tidak.

Tim
sumber
4
Anda menulis, "dan karenanya simpan 1KB RAM ini". Simpan itu untuk apa? 1KB itu harus tersedia ketika Anda membutuhkannya untuk array jadi mengapa tidak membuat alokasi statis? Apakah Anda memiliki kegunaan lain untuk memori ketika itu tidak diperlukan untuk array?
kkrambo
@kkrambo Pada titik tertentu kami menganggap sistem penuh ketika kami tidak dapat menambahkan apa pun pada RAM, apakah itu sesuatu yang statis atau di tumpukan. Jika kita meletakkan array ini di stack hanya ketika kita menggunakannya, ia akan membiarkan tempat untuk fungsi lain selama mereka tidak digunakan pada saat yang bersamaan. Tetapi pertanyaannya benar-benar sah, saat ini jika kita tidak mengubah apa pun di SW, kita tidak perlu lebih banyak RAM;)
Tim
1
Bisakah Anda memperjelas apakah array ini memiliki konten yang selalu tetap sama atau jika itu berubah ketika fungsi yang menggunakannya dipanggil?
Blrfl
@ Blrfl Ini berubah setiap kali fungsi dipanggil.
Tim

Jawaban:

8

Satu-satunya hal yang saya sadari adalah saya harus memastikan bahwa saya benar-benar memiliki 1KB stack gratis ketika memasuki fungsi ini.

Ya, dan itu adalah kendala yang kuat. Anda akan lebih yakin secara statis daripada memiliki ruang besar di stack. Jika kode ini kecil, jika Anda menggunakan GCC terbaru untuk mengkompilasi kode Anda, lihat ini .

BTW, beberapa mikroprosesor murah mungkin menggunakan bingkai panggilan "besar" lebih mahal daripada yang "normal" (misalnya karena set instruksi mereka akan memilih offset satu byte dari penunjuk tumpukan). YMMV.

Juga, jika Anda melakukan pengkodean dalam C dan jika Anda merasa bahwa array besar Anda dapat digunakan kembali untuk tujuan lain, Anda dapat mempertimbangkan untuk menjadikannya anggota serikat pekerja (dengan tipe variabel global union). Ya, itu sangat jelek.

Atau, Anda dapat mempertimbangkan pengkodean beberapa pengalokasian tumpukan primitif yang cocok untuk aplikasi Anda (dan itu bisa memiliki API yang berbeda dengan malloc& free....).

Basile Starynkevitch
sumber
1
Terima kasih, saya sebenarnya sedikit mengharapkan jawaban semacam ini, yaitu tetap dialokasikan secara statis sehingga untuk memastikan saya tidak berakhir dengan stack overflow. Sayangnya saya belum memiliki kompiler GCC terbaru dan kodenya tidak kecil.
Tim
Tidak bisakah Anda mendapatkan (mungkin dengan mengkompilasi GCC dari kode sumbernya) kompiler GCC untuk platform Anda?
Basile Starynkevitch
2
Saya sudah punya satu, itu benar-benar tua. Mengerjakan yang baru bukan pada ruang lingkup saya, juga tidak sesuai dengan jadwal saya. Tetapi tentu saja, beberapa hal akan lebih mudah dengan alat yang mutakhir.
Tim
3
Meminta bos Anda untuk memberi Anda GCC yang lebih baru (baik dengan memberi Anda alat biner terkini, atau dengan memberi Anda waktu untuk kompilasi ulang GCC) adalah hal yang berharga, karena sangat mungkin GCC yang lebih baru akan mengoptimalkan sedikit lebih baik (Anda tahu gcc -flto -Os? ) dan Anda mungkin mendapatkan beberapa memori ....
Basile Starynkevitch
2
Ada di jalur tapi itu tidak akan terjadi sebelum beberapa saat. Saya sudah menggunakan -Os pada sistem lain dengan toolchain yang lebih baru, tapi saya tidak mengetahui parameter -flto ini, terima kasih telah menunjukkannya. (Perhatikan bahwa saya telah melakukan beberapa tes dengan parameter GCC -Os dan -O1-3 beberapa minggu yang lalu pada GCC 5.4.1 dan RAM selalu sama sepanjang waktu. FLASH dan MCU menjalankan waktu yang berbeda. Itu tidak di MCU yang sama dengan yang saya sebutkan dalam tanya jawab ini
Tim
6

Orang-orang cenderung berhati-hati dengan tumpukan besar, karena itu tumbuh mundur dalam RAM dan menimpa nilai-nilai variabel, yang mengarah ke perilaku yang tidak dapat dijelaskan. Itu menjadi lebih buruk, karena Anda perlu mengetahui alamat penunjuk tumpukan serendah mungkin dan kurangi ukuran yang dialokasikan ketika memasuki rutinitas.

Ini semua adalah pekerjaan untuk manajemen memori perangkat keras (harus menghasilkan jebakan atau kesalahan ketika stack overflow) atau untuk kompiler, mengingat ia memiliki fitur untuk jenis analisis ini.

Jika tidak, Anda dapat melakukan apa yang Anda inginkan dengan RAM Anda.

Martin Sugioarto
sumber
4

Seperti jawaban sebelumnya telah menunjukkan, saya juga akan merekomendasikan meninggalkan array statis jika cocok dengan memori. Dalam kebanyakan kasus, jauh lebih penting untuk memiliki jejak memori deterministik, bahkan jika itu berarti Anda "membuang" memori untuk variabel yang tidak digunakan sepanjang waktu. Menempatkan array besar ke tumpukan Anda akan terlalu mudah meledakkannya, dan tumpukan berlebihan cenderung menyebabkan masalah yang sulit ditemukan dan sulit direproduksi (jika Anda tidak dapat menggunakan MMU untuk melindungi tumpukan).

Saran untuk berbagi blok dengan beberapa data lain dengan serikat adalah IMO valid, meskipun itu juga bisa menjadi sumber untuk masalah yang sulit ditemukan, jika Anda menemukan variabel yang salah di dalamnya.

Jika Anda kehabisan memori dan sangat perlu membuat variabel yang lebih pendek untuk membagikannya, sebelum memindahkan array ke stack, saya akan mempertimbangkan untuk menambah alokasi memori dinamis, meskipun ia memiliki kekurangannya sendiri. Dalam hal ini mungkin bukan jawaban, karena array terdengar cukup besar dibandingkan dengan memori yang tersedia.

MaKo
sumber
1

Anda memiliki satu opsi lain jika Anda memiliki semacam penyimpanan flash. Anda dapat menukar kecepatan akses ram dengan menyimpan data Anda dalam sekejap dan membaca & mencari di sana. Anda hanya perlu memuat satu catatan sekaligus ke dalam ram. Akan sedikit lebih rumit jika Anda harus dapat memperbarui catatan. Anda akan membutuhkan mekanisme level-pakai yang tersegmentasi. Saya telah melakukan ini di masa lalu dan memasukkan indeks untuk mempercepat akses.

Tereus Scott
sumber
1
Saya juga telah melakukan ini di masa lalu tetapi pertanyaan saya lebih tentang masalah yang bisa saya hadapi jika saya meletakkan ini di tumpukan, tidak benar-benar tentang alternatif untuk RAM ketika kita kekurangan itu. Terima kasih sudah menjawabnya
Tim
1

Terutama ketika bekerja dengan sistem embedded, Anda ingin sebanyak mungkin kegagalan terjadi pada waktu kompilasi dan tidak ada yang gagal pada waktu berjalan (bagus jika kita bisa mencapai ini, meskipun ...).

Membuat array besar yang mungkin Anda butuhkan dalam keadaan arbitrer dari program Anda yang dialokasikan secara statis melakukan hal itu - Linker akhirnya akan memperingatkan Anda "ini tidak cocok dengan RAM", sedangkan alokasi tumpukan hanya akan membuat program Anda macet dengan tumpukan yang sulit di-debug meluap.

tofro
sumber