aligned_malloc及aligned_free的實現及詳細解釋
有時候我們需要動態分配對齊的記憶體,例如使用SSE2指令集的時候,但C++並沒有提供分配和釋放對齊的記憶體的函式,這時候就需要我們自己動手實現一個
兩個函式原型如下
void* aligned_malloc(size_t size, size_t alignment);
void aligned_free(void *palignedmem);
alinged_malloc接受兩個size_t型別的引數,size是分配的記憶體塊位元組數,alignment是對齊數目,返回指向對齊的記憶體塊的void*指標
aligned_free接受一個void*型別的引數,是由aligned_malloc分配的對齊的記憶體塊的地址
1.aligned_malloc的實現
首先要檢查alignment是否為2的整數次冪,有一種高效的演算法:
if (alignment & (alignment - 1))
{
return nullptr; //alignment不是2的整數次冪則返回nullptr
}
else
{
//反之,分配記憶體
}
如果一個整數是2的整數次冪,那這個數用二進位制表示一定是100..000(n個零)的形式,把這個數減1,則是111...111(n個1)的形式,把這兩個數做按位與,結果一定是0.反之,結果不是零。
然後要先分配足夠大的記憶體
void *praw = malloc(sizeof(void*) + size + alignment);
這個演算法基於一個顯而易見的結論:n個連續的自然數中一定有一個數可以被n整除。為了能夠找到size位元組的alignment對齊的記憶體,至少要分配(size+alignment)位元組的記憶體。同時,為了能夠有足夠的空間來儲存整個分配的記憶體的起始地址(即praw),還需要多分配一個指標佔用位元組數的記憶體,可用sizeof(void*)得到。
在尋找alignment位元組對齊的記憶體前,要先跳過為記錄整個分配的記憶體的起始地址(即praw的地址)保留的記憶體
void *pbuf = reinterpret_cast<void*>(reinterpret_cast<size_t>(praw) + sizeof(void*));
現在開始從pbuf向上尋找alignment對齊的記憶體塊。可用用下面這個演算法
void *palignedbuf = reinterpret_cast<void*>((reinterpret_cast<size_t>(pbuf) | (alignment - 1)) + 1)
為了方便,先假設記憶體地址寬度是8位元組,並且pbuf是13,用二進位制表示是00001101。alignment是8,用二進位制表示是00001000。比pbuf大的最小的能被8整除的整數是16,用二進位制表示是00010000。這個過程可以分三步完成:1.alignment減1,得到,00000111。2.alignment與pbuf進行按位或,得到00001111。3.加上1,得到00010000,正好是比pbuf大的最小的能夠被alignment整除的數。
返回對齊的記憶體之前,先前移指標大小個位元組來儲存整個分配的記憶體的起始地址(即praw)
(static_cast<void**>(palignedbuf))[-1] = praw;
最後返回對齊的記憶體的地址
return palignedbuf;
2.aligned_free的實現
這個很簡單,分為兩步:
1.從palignedmem前移指標大小個位元組,得到整個分配的記憶體的地址
2.free記憶體
程式碼如下
free(reinterpret_cast<void*>((static_cast<void**>(palignedmem))[-1])
最後貼上完整的程式碼
void* aligned_malloc(size_t size, size_t alignment)
{
if(alignment & (alignment - 1))
{
return nullptr
}
else
{
void *praw = malloc(sizeof(void*) + size + alignment);
if(praw)
{
void *pbuf = reinterpret_cast<void*>(reinterpret_cast<size_t>(praw) + sizeof(void*));
void *palignedbuf = reinterpret_cast<void*>((reinterpret_cast<size_t>(pbuf) | (alignment - 1)) + 1);
(static_cast<void**>palignedbuf)[-1] = praw;
return palignedbuf;
}
else
{
return nullptr;
}
}
}
void aligned_free(void *palignedmem)
{
free(reinterpret_cast<void*>((static_cast<void**>palignedmem)[-1]));
}
相關文章
- Windows XP Services詳細解釋及建議(轉)Windows
- 加密、解密詳解及CA的實現加密解密
- 五、對Linux中使用者的詳細解釋及操作Linux
- ZIP壓縮演算法詳細分析及解壓例項解釋演算法
- Promise 規範解讀及實現細節 (二)Promise
- 滑動視窗濾波器原理分析及詳細程式碼講解實現
- Swift實現俄羅斯方塊詳細思路及原始碼Swift原始碼
- 設計模式詳解及Python實現設計模式Python
- **超詳細的**10種排序演算法原理及 JS 實現排序演算法JS
- 迴圈佇列的實現及細節佇列
- 手寫call、apply、bind實現及詳解APP
- 詳解301重定向及實現方法
- 六種機率資料結構的詳細解釋及應用場景資料結構
- Golang make和new的區別及實現原理詳解Golang
- Spring @Conditional註解 詳細講解及示例Spring
- tar命令的詳細解釋
- Q-Q圖原理詳解及Python實現Python
- node 訂閱釋出及實現
- ansible自動化運維詳細教程及playbook詳解運維
- JavaScript FormData的詳細介紹及使用JavaScriptORM
- rqt的安裝及詳細介紹QT
- NCNN 模型推理詳解及實戰CNN模型
- docker 命令詳細解釋Docker
- top命令詳細解釋
- Servlet、HTTP詳細解釋!ServletHTTP
- 【自動化基礎】allure描述用例詳細講解及實戰
- 令牌桶演算法原理及實現(圖文詳解)演算法
- 機器學習之決策樹詳細講解及程式碼講解機器學習
- 微信訊息體簽名及加解密功能詳細解析以及.net實現解密
- LVM詳細介紹及建立LVM
- 正規表示式詳解及實戰
- .Net for Spark 實現 WordCount 應用及除錯入坑詳解Spark除錯
- 【小白學PyTorch】13 EfficientNet詳解及PyTorch實現PyTorch
- 【小白學PyTorch】12 SENet詳解及PyTorch實現PyTorchSENet
- 單點登入的原理、實現、及技術方案比較詳解
- JPS 命令詳細解釋
- Nginx location配置詳細解釋Nginx
- resin配置檔案的詳細解釋