我有一些奇怪的问题,我正在研究一些SSE2和AVX代码.我正在使用GCC构建我的应用程序,运行时cpu特征检测.对象文件使用每个CPU功能的单独标志构建,例如:
g++ -c -o ConvertSamples_SSE.o ConvertSamples_SSE.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse
g++ -c -o ConvertSamples_SSE2.o ConvertSamples_SSE2.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse2
g++ -c -o ConvertSamples_AVX.o ConvertSamples_AVX.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -mavx
Run Code Online (Sandbox Code Playgroud)
当我第一次启动该程序时,我发现SSE2例程正常,非SSE例程的速度提升(大约快100%).在我运行任何AVX例程之后,完全相同的SSE2例程现在运行得慢得多.
有人可以解释一下这可能是什么原因吗?
在AVX例程运行之前,所有测试都比FPU数学运算快大约80-130%,如此处所示,在AVX例程运行之后,SSE例程要慢得多.
如果我跳过AVX测试程序,我从未看到这种性能损失.
这是我的SSE2例程
void Float_S16(const float *in, int16_t *out, const unsigned int samples)
{
static float ratio = (float)Limits<int16_t>::range() / (float)Limits<float>::range();
static __m128 mul = _mm_set_ps1(ratio);
unsigned int i;
for (i = 0; i < samples - 3; i += 4, …
Run Code Online (Sandbox Code Playgroud) 我正在构建一个嵌入式项目,显示从显示器上的GPS模块检索的时间,但我还想显示当前日期.我目前有时间作为unix时间戳,而progject是用C语言编写的.
我正在寻找一种从时间戳计算当前UTC日期的方法,考虑到闰年?请记住,这是针对没有FPU的嵌入式项目,因此模拟浮点数学,尽可能避免性能.
编辑
在看了@R ...的代码之后,我决定自己写一篇文章并提出以下内容.
void calcDate(struct tm *tm)
{
uint32_t seconds, minutes, hours, days, year, month;
uint32_t dayOfWeek;
seconds = gpsGetEpoch();
/* calculate minutes */
minutes = seconds / 60;
seconds -= minutes * 60;
/* calculate hours */
hours = minutes / 60;
minutes -= hours * 60;
/* calculate days */
days = hours / 24;
hours -= days * 24;
/* Unix time starts in 1970 on a Thursday */
year = 1970;
dayOfWeek = 4; …
Run Code Online (Sandbox Code Playgroud) 我正在开发一个应用程序,它将-1.0到1.0范围内的Float样本转换为带符号的16位,以确保优化(SSE)例程的输出是准确的我已编写了一组运行非优化版本的测试SSE版本并比较它们的输出.
在开始之前,我已经确认SSE舍入模式设置为最接近.
在我的测试用例中,公式为:
ratio = 65536 / 2
output = round(input * ratio)
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,结果是准确的,但在一个特定的输入上,我看到输入失败-0.8499908447265625
.
-0.8499908447265625 * (65536 / 2) = -27852.5
Run Code Online (Sandbox Code Playgroud)
正常代码正确地将其舍入为-27853
,但SSE代码将此舍入为-27852
.
这是使用中的SSE代码:
void Float_S16(const float *in, int16_t *out, const unsigned int samples)
{
static float ratio = 65536.0f / 2.0f;
static __m128 mul = _mm_set_ps1(ratio);
for(unsigned int i = 0; i < samples; i += 4, in += 4, out += 4)
{
__m128 xin;
__m128i con;
xin = _mm_load_ps(in);
xin = _mm_mul_ps(xin, …
Run Code Online (Sandbox Code Playgroud) 我正在编写一个执行音频处理的SSE方法的问题.我在这里基于英特尔的论文实现了一个SSE随机函数:
我还有一个使用SSE执行从Float到S16的转换的方法,转换执行非常简单,如下所示:
unsigned int Float_S16LE(float *data, const unsigned int samples, uint8_t *dest)
{
int16_t *dst = (int16_t*)dest;
const __m128 mul = _mm_set_ps1((float)INT16_MAX);
__m128 rand;
const uint32_t even = count & ~0x3;
for(uint32_t i = 0; i < even; i += 4, data += 4, dst += 4)
{
/* random round to dither */
FloatRand4(-0.5f, 0.5f, NULL, &rand);
__m128 rmul = _mm_add_ps(mul, rand);
__m128 in = _mm_mul_ps(_mm_load_ps(data),rmul);
__m64 con = _mm_cvtps_pi16(in);
memcpy(dst, &con, sizeof(int16_t) * 4);
}
}
Run Code Online (Sandbox Code Playgroud)
FloatRand4定义如下: …
我正在编写一个程序,需要极低延迟的纹理来屏幕流(10ms以下),我已经实现了这个使用GL_ARB_buffer_storage
,它非常适合流式传输,而vsync则可以防止撕裂.
但是我发现NVidia管道在阻塞之前调用交换缓冲区时会缓冲2到8帧,我需要防止这种情况.
我所做的是以下内容:
uint64_t detectPresentTime()
{
// warm up first as the GPU driver may have multiple buffers
for(int i = 0; i < 10; ++i)
glxSwapBuffers(state.renderer);
// time 10 iterations and compute the average
const uint64_t start = microtime();
for(int i = 0; i < 10; ++i)
glxSwapBuffers(state.renderer);
const uint64_t t = (microtime() - start) / 10;
// ensure all buffers are flushed
glFinish();
DEBUG_INFO("detected: %lu (%f Hz)", t, 1000000.0f / t);
return t;
}
Run Code Online (Sandbox Code Playgroud)
然后在绘制线程中我执行以下操作:
uint64_t …
Run Code Online (Sandbox Code Playgroud) 我写了一个简单的测试(代码在底部)来memcpy
对我的 64 位 Debian 系统的性能进行基准测试。在我的系统上编译为 64 位二进制文件时,这在所有块大小上提供了一致的 38-40GB/s。然而,当在同一系统上构建为 32 位二进制文件时,复制性能非常糟糕。
我在汇编程序中编写了自己的 memcpy 实现,该实现利用了能够匹配 64 位性能的 SIMD。老实说,我自己的 memcpy 比原生的快得多,这让我感到震惊,当然 32 位 libc 构建肯定有问题。
0x00100000 B, 0.034215 ms, 29227.06 MB/s (16384 iterations)
0x00200000 B, 0.033453 ms, 29892.56 MB/s ( 8192 iterations)
0x00300000 B, 0.048710 ms, 20529.48 MB/s ( 5461 iterations)
0x00400000 B, 0.049187 ms, 20330.54 MB/s ( 4096 iterations)
0x00500000 B, 0.058945 ms, 16965.01 MB/s ( 3276 iterations)
0x00600000 B, 0.060735 ms, 16465.01 MB/s ( 2730 iterations)
0x00700000 B, …
Run Code Online (Sandbox Code Playgroud) 我现在想不清楚,我想通过station_id返回计数,输出的例子是:
station 1有3个fb帖子,6个linkedin帖子,5个邮件帖子站2个有3个fb帖子,6个linkedin帖子,5个邮件帖子
所以我需要按站ID分组,我的表结构是
CREATE TABLE IF NOT EXISTS `posts` (
`post_id` bigint(11) NOT NULL auto_increment,
`station_id` varchar(25) NOT NULL,
`user_id` varchar(25) NOT NULL,
`dated` datetime NOT NULL,
`type` enum('fb','linkedin','email') NOT NULL,
PRIMARY KEY (`post_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=x ;
Run Code Online (Sandbox Code Playgroud)
到目前为止我的查询是返回0站,当它有一个时有2个帖子(db tho中有2个)
SELECT Station_id, (select count(*) FROM posts WHERE type = 'linkedin') AS linkedin_count, (select count(*) FROM posts WHERE type = 'fb') AS fb_count, (select count(*) FROM posts WHERE type = 'email') AS email_count FROM `posts` GROUP BY station_id;
Run Code Online (Sandbox Code Playgroud) 我正在编写一个全局钩子来纠正 Matrox TripleHead2Go 等平台上的三头监视器窗口定位,到目前为止,它对于 32 位程序运行良好,但现在我需要构建 64 位版本,我需要一些翻译方面的帮助我在每个窗口类上安装了 wndproc thunk 的 x86 操作码。
thunk 向 wndproc 调用添加一个额外的参数,这是原始的 wndproc 地址,以便我的 wndproc 处理程序可以在最后调用它。
#ifdef _WIN64
//TODO: figure out the WIN64 instructions
#else
const unsigned char PatchTemplate[] =
{
0x90, // nop, will become int3 if debug = true
0x58, // pop eax (get the return address)
0x68, 0x00, 0x00, 0x00, 0x00, // push imm32, original wndproc address
0x50, // push eax (restore the return address)
0x68, 0x00, 0x00, 0x00, 0x00, // push …
Run Code Online (Sandbox Code Playgroud)