小编Geo*_*rey的帖子

使用AVX后,SSE运行缓慢

我有一些奇怪的问题,我正在研究一些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)

c++ x86 gcc avx sse2

10
推荐指数
1
解决办法
762
查看次数

将unix时间戳转换为没有系统库的日期

我正在构建一个嵌入式项目,显示从显示器上的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)

c embedded timestamp date

9
推荐指数
1
解决办法
2万
查看次数

当它应该向上舍入时,SSE会向下舍入

我正在开发一个应用程序,它将-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)

c++ x86 sse rounding-error intrinsics

8
推荐指数
2
解决办法
1072
查看次数

SSE内在函数导致正常的float操作返回-1.#INV

我正在编写一个执行音频处理的SSE方法的问题.我在这里基于英特尔的论文实现了一个SSE随机函数:

http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/

我还有一个使用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定义如下: …

c++ sse intrinsics

7
推荐指数
1
解决办法
530
查看次数

防止OpenGL缓冲帧

我正在编写一个程序,需要极低延迟的纹理来屏幕流(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)

c linux opengl amd nvidia

5
推荐指数
1
解决办法
290
查看次数

对于大缓冲区,为什么在 Ryzen 上使用 gcc -march=native 在 32 位模式下 memcpy 很慢?

我写了一个简单的测试(代码在底部)来memcpy对我的 64 位 Debian 系统的性能进行基准测试。在我的系统上编译为 64 位二进制文​​件时,这在所有块大小上提供了一致的 38-40GB/s。然而,当在同一系统上构建为 32 位二进制文​​件时,复制性能非常糟糕。

我在汇编程序中编写了自己的 memcpy 实现,该实现利用了能够匹配 64 位性能的 SIMD。老实说,我自己的 memcpy 比原生的快得多,这让我感到震惊,当然 32 位 libc 构建肯定有问题。

32位memcpy测试结果

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)

c performance x86 memcpy amd-processor

5
推荐指数
1
解决办法
610
查看次数

如何使用sql子查询进行分组

我现在想不清楚,我想通过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)

mysql sql

4
推荐指数
1
解决办法
7061
查看次数

将 x86 操作码转换为 64 位版本

我正在编写一个全局钩子来纠正 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)

x86 assembly x86-64 32bit-64bit

2
推荐指数
1
解决办法
1571
查看次数