[英]Efficient way to convert a 16-bit short array to a 32-bit int array?
將無符號短數組(每個值16位)轉換為無符號整數數組(每個值32位)的最有效方法是什么?
復制它。
unsigned short source[]; // …
unsigned int target[]; // …
unsigned short* const end = source + sizeof source / sizeof source[0];
std::copy(source, end, target);
std::copy
內部選擇給定輸入類型的最佳復制機制。 但是,在這種情況下,可能沒有比在循環中單獨復制元素更好的方法了。
在C ++中使用std::copy
:
#include<algorithm> //must include
unsigned short ushorts[M]; //where M is some const +ve integer
unsigned int uints[N]; //where N >= M
//...fill ushorts
std::copy(ushorts, ushorts+M, uints);
在C語言中,使用手動循環(實際上,您可以在C和C ++中使用手動循環):
int i = 0;
while( i < M ) { uints[i] = ushorts[i]; ++i; }
這里是一個以64位塊訪問的展開循環。 它可能比簡單循環快一點,但測試是唯一可以知道的方法。
假設N是4的倍數,那個sizeof(short)是16位,並且使用64位寄存器。
typedef union u {
uint16_t us[4];
uint32_t ui[2];
uint64_t ull;
} u_t;
ushort_t src[N] = ...;
uint_t dst[N];
u_t *p_src = (u_t *) src;
u_t *p_dst = (u_t *) dst;
uint_t i;
u_t tmp, tmp2;
for(i=0; i<N/4; i++) {
tmp = p_src[i]; /* Read four shorts in one read access */
tmp2.ui[0] = tmp.us[0]; /* The union trick avoids complicated shifts that are furthermore dependent on endianness. */
tmp2.ui[1] = tmp.us[1]; /* The compiler should take care of optimal assembly decomposition. */
p_dst[2*i] = tmp2; /* Write the two first ints in one write access. */
tmp2.ui[0] = tmp.us[2];
tmp2.ui[1] = tmp.us[3];
p_dst[2*i+1] = tmp2; /* Write the 2 next ints in 1 write access. */
}
編輯
所以我只是在具有GCC 3.4.1的SUN M5000(SPARC64 VII 2.5 GHz)上以64位模式在4,000,000個元件陣列上進行了測試。 天真的實現速度要快一些。 我嘗試使用SUNStudio 12和GCC 4.3,但由於數組大小,我甚至無法編譯程序。
EDIT2
我設法在GCC 4.3上編譯它。 優化版本比天真版本快一點。
GCC 3.4 GCC 4.3
naive 11.1 ms 11.8 ms
optimized 12.4 ms 10.0 ms
EDIT3
我們可以從中得出結論,就C而言,不要為復制循環的優化版本而煩惱,增益是如此之低,以至於錯誤的風險超過了收益。
關於什么
unsigned short src[N] = ...;
unsigned int dst[N];
for(i=0; i<N; ++i)
dst[i] = src[i];
對於C ++版本,Konrad或Nawaz的答案肯定更適合。
short[]
相同的長度初始化int[]
short[]
。 short[]
分配i
個所述的元件short[]
到i
個所述的位置int[]
在許多體系結構中,遞減的do-while
可能比這里提出的for
和while
循環更快。 就像是:
unsigned short ushorts[M];
unsigned int uints[N];
int i = M-1;
do{
uints[i] = ushorts[i];
i--;
} while(i >= 0);
編譯器可以處理大多數優化,例如循環展開,但通常上述速度更快(在許多體系結構上),因為:
do-while
對一個while
或for
也可能有更快的方法,例如完全使用指針算法。 這可能會變成一種有趣的練習,即拆解代碼並進行分析以查看哪些代碼更快。 它取決於所有架構。 幸運的是,其他人已經使用std :: copy為您完成了這項工作。
只需復制短數組的地址即可訪問短數組的每個元素,如pTp32[0...LEN-1].arr[0..1]
:
unsigned short shrtArray[LEN]; //..
union type32
{
short arr[2];
int value;
};
type32 * pTp32 = (type32*)shrtArray;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.