在 Windows 上优化 memcpy (MSVC++)
Optimize memcpy on Windows (MSVC++)
假设我想复制#SIZE 号。从一个数组到另一个数组的整数。我看到以下 3 个的性能不同,即使它们完成相同的工作:
memcpy((char*)(arr), (char*)(temp), sizeof(int) * size);
memcpy((int*)(arr), (int*)(temp), size);
memcpy((double*)(arr), (double*)(temp), size/(sizeof(double)/sizeof(int)));
计时分别为 160 us、40 us 和 20 us(对于 100 万整数的大小)。我知道在每种情况下使用的寄存器大小不同,但我期望 MSVC 编译器通过使用最高(向量)寄存器大小来优化所有这些。内存对齐可以通过创建剥离和剩余循环来实现。也有可能使用 non-temporal/streaming 商店。有没有办法在编译器中强制进行这种优化?
另外,有什么方法可以在 MSVC 中强制内联 memcpy 吗?
even though they accomplish the same job
不,那不是真的。
memcpy
的最后一个参数是长度,字节数,不是项目数。你的第二行做的工作少了四倍,只复制了你想要的四分之一(或者第一行复制了四倍太多)。
memcpy
总是复制字节,而您似乎假设它复制您传递的类型(int
或 double
)。来自 cppreference:
Copies count bytes from the object pointed to by src to the object pointed to by dest. Both objects are reinterpreted as arrays of unsigned char.
由于您的三个调用确实复制了不同数量的字节,因此运行时的差异是可以预料的。如果 sizeof(int) == 4
和 double
是您平台上 int
大小的两倍,则您测量的时间是一致的。
其他答案都很好的说明了问题,我就加点数字说明一下:
memcpy((char*)(arr), (char*)(temp), sizeof(int) * size);
第一次调用复制了 sizeof(int) * size
字节,这很可能是 4 * size
字节。它需要 160 微秒。
memcpy((int*)(arr), (int*)(temp), size);
第二次调用复制size
字节,因此少了4倍,也少了4倍的时间,即160/4 = 40 微秒.
memcpy((double*)(arr), (double*)(temp), size/(sizeof(double)/sizeof(int)));
第三次调用复制 size/(sizeof(double)/sizeof(int))
字节,这很可能是 size/(8/4)
,因此 size/2
字节 。这分别比第一种和第二种情况少八倍和两倍。需要 160/8 = 40/2 = 20 微秒.
因此,运行时间与复制的字节数完全成正比。
假设我想复制#SIZE 号。从一个数组到另一个数组的整数。我看到以下 3 个的性能不同,即使它们完成相同的工作:
memcpy((char*)(arr), (char*)(temp), sizeof(int) * size);
memcpy((int*)(arr), (int*)(temp), size);
memcpy((double*)(arr), (double*)(temp), size/(sizeof(double)/sizeof(int)));
计时分别为 160 us、40 us 和 20 us(对于 100 万整数的大小)。我知道在每种情况下使用的寄存器大小不同,但我期望 MSVC 编译器通过使用最高(向量)寄存器大小来优化所有这些。内存对齐可以通过创建剥离和剩余循环来实现。也有可能使用 non-temporal/streaming 商店。有没有办法在编译器中强制进行这种优化?
另外,有什么方法可以在 MSVC 中强制内联 memcpy 吗?
even though they accomplish the same job
不,那不是真的。
memcpy
的最后一个参数是长度,字节数,不是项目数。你的第二行做的工作少了四倍,只复制了你想要的四分之一(或者第一行复制了四倍太多)。
memcpy
总是复制字节,而您似乎假设它复制您传递的类型(int
或 double
)。来自 cppreference:
Copies count bytes from the object pointed to by src to the object pointed to by dest. Both objects are reinterpreted as arrays of unsigned char.
由于您的三个调用确实复制了不同数量的字节,因此运行时的差异是可以预料的。如果 sizeof(int) == 4
和 double
是您平台上 int
大小的两倍,则您测量的时间是一致的。
其他答案都很好的说明了问题,我就加点数字说明一下:
memcpy((char*)(arr), (char*)(temp), sizeof(int) * size);
第一次调用复制了 sizeof(int) * size
字节,这很可能是 4 * size
字节。它需要 160 微秒。
memcpy((int*)(arr), (int*)(temp), size);
第二次调用复制size
字节,因此少了4倍,也少了4倍的时间,即160/4 = 40 微秒.
memcpy((double*)(arr), (double*)(temp), size/(sizeof(double)/sizeof(int)));
第三次调用复制 size/(sizeof(double)/sizeof(int))
字节,这很可能是 size/(8/4)
,因此 size/2
字节 。这分别比第一种和第二种情况少八倍和两倍。需要 160/8 = 40/2 = 20 微秒.
因此,运行时间与复制的字节数完全成正比。