将无符号短数组(每个值16位)转换为无符号整数数组(每个值32位)的最有效方法是什么?
答案 0 :(得分:14)
复制它。
unsigned short source[]; // …
unsigned int target[]; // …
unsigned short* const end = source + sizeof source / sizeof source[0];
std::copy(source, end, target);
std::copy
在内部为给定的输入类型选择了最佳的复制机制。但是,在这种情况下,可能没有比在循环中单独复制元素更好的方法了。
答案 1 :(得分:9)
在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; }
答案 2 :(得分:6)
这里是一个以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而言,不要为复制循环的优化版本而烦恼,增益太低,以至于错误的风险超过了收益。
答案 3 :(得分:2)
怎么样?
unsigned short src[N] = ...;
unsigned int dst[N];
for(i=0; i<N; ++i)
dst[i] = src[i];
对于C ++版本,Konrad或Nawaz的答案肯定更适合。
答案 4 :(得分:1)
int[]
相同的长度初始化short[]
。short[]
进行迭代,将i
的{{1}} th 元素分配给short[]
th i
。答案 5 :(得分:1)
在许多体系结构中,递减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完成了这项工作。
答案 6 :(得分:1)
只需复制短数组的地址即可访问短数组的每个元素,例如pTp32[0...LEN-1].arr[0..1]
:
unsigned short shrtArray[LEN]; //..
union type32
{
short arr[2];
int value;
};
type32 * pTp32 = (type32*)shrtArray;