※ 引述《anoymouse (沒有暱稱)》之銘言:
: 標題: [問題] 8-bit系統還是要data alignment嗎?
: 時間: Mon Feb 22 22:36:04 2016
:
: 如提
:
: 在讀data alignment 碰到一些問題
:
: 1.如果每次都是1 byte抓資料,那就不會有misaligned了問題吧?
: 還是說不管什麼系統都要照資料大小的倍數來排記憶體位址? 感覺8bit沒必要啊
講「系統」還是太籠統了一點。
這東西必須翻閱你平台的 ISA (Instruction Set Architecture) 文件,
看看裡面有沒有支援大於 8-bit 的運算指令 (如果有的話大概也是多週期的)。
如果有的話,一般也能在 Programming Guide 裡看到一些提示跟範例。
另外,如果有 CPU 以外的週邊裝置,有時是週邊裝置有不同的 alignment 要求。
這種時候,在記憶體擺資料當然就是照週邊裝置的需求去擺。
:
: 2.
: http://www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packi
: ng/(縮網好像不能用 抱歉)
: 這網站很下面講的General Questions 第二點
: 請問是什麼意思? 如果是32位元系統不是一律抓32bit嗎 不管放在哪一條bank有差嗎?
其實這問題問得不好,他想講的只是一個 char 被放在 4 bytes 裡的哪個 byte 罷了。
如果硬體設計上就是只能呆板地一次讀 4 bytes,那就是如他所說,
若不是被放在最右邊的 byte (即 bank 0),那硬體讀 4 bytes 以後會用 shift 處理。
: 這時候又想問 多抓的24bits怎麼辦? 再擺回去?
丟掉就好了,又沒用到。
: 3.Pointer Mishaps 不過似乎沒有很詳細 只是說pointer有可能會有
: misaligned 主要是下一段說malloc
很簡單啊,因為你不知道 void * 這指標是不是指在 4-byte 邊界上。
萬一不是,你想從這裡讀一個 int 出來,讀記憶體的指令收到的位址就是 misaligned。
如果這個 CPU 沒有提供 unaligned load 指令,那就會發 exception 出來。
一般來說會有人實作好 exception handler 處理掉這問題,方法就是上面講的讀兩次。
如果指令支援,你可能會期望 compiler 選用 unaligned load 指令。
但這個是看 compiler 實作決定,而 compiler 如果覺得 unaligned load 比較貴,
那麼 compiler 也可能一律採用普通的 load 指令去處理 dereference void * 的狀況。
畢竟 malloc () 傳回 void *,實作上又往往會保證 malloc () 傳回的位址是 aligned,
那麼如果 unaligned load 指令所需的 cycle 數較多,compiler 可能就不會選用它。
這些部分是看實作決定,所以一樣要讀你平台的 Programming Guide 才能知道。
一般低階的 CPU 沒什麼特殊設計的話,unaligned load 也是靠 multi-cycle 完成。
有切 pipeline 的 CPU 可能在 decode 完後拆成三個 micro operations,
分別是做兩次 load 還有一次調整合併的動作,能 forward 結果的 stage 較晚。
高階一點 CPU 的 data bus 可能為了一些考量做成 64-bit,
然後因為本來一些乘法和乘加指令就會寫入兩個 registers (有兩個 write ports),
所以 unaligned load 指令可以一口氣從記憶體讀出兩個 32-bit 資料。
不過合併的部分通常因為高階 CPU 的 clock rate 高導致 timing 來不及,
還是需要多一個 cycle 才能把兩筆 data 調整並合併好。
這些特性都會導致 unaligned load 指令的成本較高,compiler 不喜歡選用,
除非 compiler 完全確定這次 load 是 unaligned,不然還是會傾向使用一般 load。
: "It is usually aligned to 8 byte boundary on 32 bit machines."
: 回傳的地址是32bit怎麼會是8byte? 求解!
你是不是忘了前面你才剛讀過 structc_tag 裡跟 double 有關的內文?
:
:
: 謝謝
:
:
: 目前從網頁所學習到的是: 網頁上所表示的bank的記憶體位址從0開始,似乎是
: offset的量,但是為了方便計算,所以假裝是記憶體的位址。
:
:
: 我的理解是 以他所舉例,32bit系統,bank所配置的來說都是一次抓4bytes,所以bank
: 是從bank0~bank3
: 放滿就換下一列,因為一次抓4bytes的關係,又是從0開始找吧,所以每4,4,4,4......
: 的找就得符合資料型別倍數的原則。如果int的資料從bank2開始放,那在抓的時候只會
: 抓到一半,還要在一個工作周期才會抓到下一半。
:
: 雖然short"貌似"從bank1開始放好像沒問題,不過根據系統的一致性是最容易設計的
: 原則,讓所有的type都符合倍數的記憶體配置,只好讓short只能放在2的倍數的記憶
: 體位址這是我猜的)
如果 CPU 提供 half-word 的 load 指令,也就是 2-byte 的 load 指令,
那麼一般預期的是資料要放在 2-byte boundary 上,否則可能發生 exception。
所以 short 放在 bank 0 或 bank 2 才是比較好的。
但是我實在不太喜歡他用 bank 幾來講這觀念,習慣上是說對齊 2-byte 邊界。
另外,上面講的 exception 只是可能會被丟出來,不代表所有平台都這樣做。
你的 ISA 文件或 Programming Guide 應該要告訴你會發生什麼,
因為也可能就真的是只讀一半就不讀下去了,叫你後果自負。
: 而padding是因為struct裡面有各種資料型別,如果建一個結構陣列,結構跟結構之間
: 內部的變數位址都得data alignment,以免下一個結構的資料misaligned。
這同時也告訴你為什麼習慣上 malloc () 傳回的位址會對齊 8-byte 邊界,
因為你可能寫 malloc(sizeof(double) * 10) 來做一個 double 動態陣列。
: 所以作者開頭提到的四個struct就還看得懂。