相关疑难解决方法(0)

取消优化英特尔Sandybridge系列CPU中管道的程序

我一直在绞尽脑汁想要完成这项任务一周,我希望有人能带领我走向正确的道路.让我从教师的指示开始:

您的作业与我们的第一个实验作业相反,即优化素数计划.你在这个任务中的目的是使程序失望,即让它运行得更慢.这两个都是CPU密集型程序.他们需要几秒钟才能在我们的实验室电脑上运行.您可能无法更改算法.

要取消优化程序,请使用您对英特尔i7管道如何运行的了解.想象一下重新排序指令路径以引入WAR,RAW和其他危险的方法.想一想最小化缓存有效性的方法.恶魔无能.

该作业选择了Whetstone或Monte-Carlo程序.缓存有效性评论大多只适用于Whetstone,但我选择了Monte-Carlo模拟程序:

// Un-modified baseline for pessimization, as given in the assignment
#include <algorithm>    // Needed for the "max" function
#include <cmath>
#include <iostream>

// A simple implementation of the Box-Muller algorithm, used to generate
// gaussian random numbers - necessary for the Monte Carlo method below
// Note that C++11 actually provides std::normal_distribution<> in 
// the <random> library, which can be used instead of this function
double gaussian_box_muller() {
  double x = 0.0;
  double y = 0.0; …
Run Code Online (Sandbox Code Playgroud)

c++ optimization x86 intel cpu-architecture

313
推荐指数
4
解决办法
4万
查看次数

num ++是'int num'的原子吗?

一般地,对于int num,num++(或++num),作为读-修改-写操作中,是不是原子.但我经常看到编译器,例如GCC,为它生成以下代码(在这里尝试):

在此输入图像描述

由于第5行对应于num++一条指令,我们可以得出结论,在这种情况下num++ 是原子的吗?

如果是这样,是否意味着如此生成num++可以在并发(多线程)场景中使用而没有任何数据争用的危险(例如,我们不需要制作它,std::atomic<int>并强加相关成本,因为它是无论如何原子)?

UPDATE

请注意,这个问题不是增量是否原子的(它不是,而且是问题的开头行).它是否可以在特定场景中,即在某些情况下是否可以利用单指令性质来避免lock前缀的开销.而且,作为公认的答案约单处理器的机器,还有部分提到这个答案,在其评论和其他人谈话解释,它可以(尽管不是C或C++).

c c++ assembly multithreading atomic

148
推荐指数
8
解决办法
1万
查看次数

什么时候使用volatile多线程?

如果有两个线程访问全局变量,那么许多教程都说使变量volatile变为阻止编译器将变量缓存在寄存器中,从而无法正确更新.但是,访问共享变量的两个线程是通过互斥锁来调用保护的东西不是吗?但是在这种情况下,在线程锁定和释放互斥锁之间,代码处于一个关键部分,只有那个线程可以访问变量,在这种情况下变量不需要是volatile?

那么多线程程序中volatile的用途/目的是什么?

c++ concurrency multithreading atomic volatile

121
推荐指数
3
解决办法
5万
查看次数

C++是否读取和写入了原子?

我有两个线程,一个更新一个int,另一个读取它.这是一个统计值,其中读取和写入的顺序无关紧要.

我的问题是,我是否需要同步访问这个多字节值?或者,换句话说,写入的一部分可以完成并被中断,然后读取就会发生.

例如,假设值= 0x0000FFFF,其值递增为0x00010000.

是否有时间值看起来像0x0001FFFF,我应该担心?当然,类型越大,发生这种情况的可能性就越大.

我总是同步这些类型的访问,但很好奇社区的想法.

c++ multithreading synchronization

79
推荐指数
4
解决办法
3万
查看次数

std :: atomic的锁在哪里?

如果数据结构中包含多个元素,则它的原子版本不能(始终)无锁.我被告知这对于较大的类型是正确的,因为CPU不能在不使用某种锁的情况下以原子方式更改数据.

例如:

#include <iostream>
#include <atomic>

struct foo {
    double a;
    double b;
};

std::atomic<foo> var;

int main()
{
    std::cout << var.is_lock_free() << std::endl;
    std::cout << sizeof(foo) << std::endl;
    std::cout << sizeof(var) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出(Linux/gcc)是:

0
16
16
Run Code Online (Sandbox Code Playgroud)

由于原子和foo大小相同,我不认为锁存储在原子中.

我的问题是:
如果一个原子变量使用一个锁,它存储在哪里,这对该变量的多个实例意味着什么?

c++ x86 atomic c++11 stdatomic

67
推荐指数
3
解决办法
4729
查看次数

SSE指令:哪些CPU可以进行原子16B内存操作?

考虑在x86 CPU上进行单个内存访问(单个读取或单个写入,而不是读取或写入)SSE指令.该指令访问16字节(128位)的存储器,访问的存储器位置对齐为16字节.

文档"英特尔®64架构内存订购白皮书"指出,对于"读取或写入地址在8字节边界上对齐的四字(8字节)的指令",内存操作似乎作为单个内存访问执行,而不管记忆类型.

问题:是否存在Intel/AMD/etc x86 CPU,它们保证读取或写入与16字节边界对齐的16字节(128位)作为单个内存访问执行?是这样,它是哪种特定类型的CPU(Core2/Atom/K8/Phenom/...)?如果您对此问题提供答案(是/否),请同时指定用于确定答案的方法 - PDF文档查找,强力测试,数学证明或您用于确定答案的任何其他方法.

此问题涉及http://research.swtch.com/2010/02/off-to-races.html等问题


更新:

我在C中创建了一个可以在您的计算机上运行的简单测试程序.请在您的Phenom,Athlon,Bobcat,Core2,Atom,Sandy Bridge或您碰巧拥有的任何支持SSE2的CPU上编译并运行它.谢谢.

// Compile with:
//   gcc -o a a.c -pthread -msse2 -std=c99 -Wall -O2
//
// Make sure you have at least two physical CPU cores or hyper-threading.

#include <pthread.h>
#include <emmintrin.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

typedef int v4si __attribute__ ((vector_size (16)));
volatile v4si x;

unsigned n1[16] __attribute__((aligned(64)));
unsigned n2[16] __attribute__((aligned(64)));

void* thread1(void *arg) {
        for (int i=0; i<100*1000*1000; i++) { …
Run Code Online (Sandbox Code Playgroud)

concurrency x86 sse atomic thread-safety

30
推荐指数
3
解决办法
7100
查看次数

对齐一个部分的开头是什么意思?

对齐一个部分的开头是什么意思?

例如:

 align 4
 a: dw 0
Run Code Online (Sandbox Code Playgroud)

它如何节省内存访问?

assembly

27
推荐指数
3
解决办法
5万
查看次数

bool读/写操作可以在x86上不是原子操作吗?

假设我们有两个线程,一个是在循环中读取bool而另一个可以在特定时间切换它.我个人认为这应该是原子的,因为sizeof(bool)在C++中是1个字节而你不是部分读/写字节但我想100%肯定.

那么是或否?

编辑:

另外供将来参考,同样适用于int

c++ x86 boolean atomic

27
推荐指数
3
解决办法
1万
查看次数

现代x86硬件可以不将单个字节存储到内存中吗?

说到C++的并发内存模型,Stroustrup的C++编程语言,第4版,第1节.41.2.1,说:

...(像大多数现代硬件一样)机器无法加载或存储任何小于单词的东西.

但是,我的x86处理器,几年前,可以存储小于一个字的对象.例如:

#include <iostream>
int main()
{
    char a =  5;
    char b = 25;
    a = b;
    std::cout << int(a) << "\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果没有优化,GCC将其编译为:

        [...]
        movb    $5, -1(%rbp)   # a =  5, one byte
        movb    $25, -2(%rbp)  # b = 25, one byte
        movzbl  -2(%rbp), %eax # load b, one byte, not extending the sign
        movb    %al, -1(%rbp)  # a =  b, one byte
        [...]
Run Code Online (Sandbox Code Playgroud)

评论是由我提出的,但是汇编是由GCC提出的.当然,它运行良好.

显然,我不明白Stroustrup在谈到硬件可以加载和存储任何小于一个单词的内容时所说的内容.据我所知,我的计划什么也不做,但加载和存储对象小于一个字的.

C++对零成本,硬件友好的抽象的彻底关注使C++与其他易于掌握的编程语言区别开来.因此,如果Stroustrup在公交车上有一个有趣的信号心理模型,或者有其他类似的东西,那么我想了解Stroustrup的模型.

什么 Stroustrup谈论,拜托?

更长时间的背景声明 …

c++ concurrency x86 assembly memory-model

25
推荐指数
2
解决办法
1869
查看次数

如何在x64上为我的进程启用对齐异常?

我很想知道我的64位应用程序是否存在对齐错误.

IPF,x86和x64上的Windows数据对齐:

在Windows中,生成对齐错误的应用程序将引发异常,EXCEPTION_DATATYPE_MISALIGNMENT.

  • 在x64体系结构上,默认情况下禁用对齐异常,并且修复由硬件完成.应用程序可以通过设置几个寄存器位来启用对齐异常,在这种情况下,除非用户使操作系统屏蔽异常,否则将引发异常SEM_NOALIGNMENTFAULTEXCEPT.(有关详细信息,请参阅AMD体系结构程序员手册第2卷:系统编程.)

[编者按:强调我的]

  • 在x86体系结构中,操作系统不会使对齐故障对应用程序可见.在这两个平台上,您还会在对齐故障方面遇到性能下降,但它的严重程度将远远低于Itanium,因为硬件将对内存进行多次访问以检索未对齐的数据.

  • 在Itanium上,默认情况下,操作系统(OS)将使该异常对应用程序可见,并且在这些情况下终止处理程序可能很有用.如果您没有设置处理程序,那么您的程序将挂起或崩溃.在清单3中,我们提供了一个示例,说明如何捕获EXCEPTION_DATATYPE_MISALIGNMENT异常.

忽略了参考AMD架构程序员手册的方向,我将参考英特尔64和IA-32架构软件开发人员手册

5.10.5检查对齐

当CPL为3时,可以通过设置CR0寄存器中的AM标志和EFLAGS寄存器中的AC标志来检查存储器参考的对齐情况.未对齐的内存引用会生成对齐异常(#AC).在特权级别0,1或2下操作时,处理器不会生成对齐异常.有关在启用对齐检查时对齐要求的说明,请参阅表6-7.

优秀.我不确定这意味着什么,但非常好.

然后还有:

2.5控制寄存器

控制寄存器(CR0,CR1,CR2,CR3和CR4;见图2-6)确定处理器的操作模式和当前正在执行的任务的特性.在所有32位模式和兼容模式下,这些寄存器均为32位.

在64位模式下,控制寄存器扩展到64位.MOV CRn指令用于操作寄存器位.这些指令的操作数大小前缀将被忽略.

控制寄存器总结如下,并且这些控制寄存器中的每个架构定义的控制字段被单独描述.在图2-6中,64位模式下寄存器的宽度用括号表示(CR0除外).- CR0 - 包含控制处理器的操作模式和状态的系统控制标志

在此输入图像描述

AM
对齐掩码(CR0的第18位) - 设置时启用自动对齐检查; 清除时禁用对齐检查.仅当AM标志置位,EFLAGS寄存器中的AC标志置位,CPL为3,处理器工作在受保护或虚拟8086模式时,才执行对齐检查.

我试过了

我实际使用的语言是Delphi,但假装它是与语言无关的伪代码:

void UnmaskAlignmentExceptions()
{
   asm
      mov rax, cr0; //copy CR0 flags into RAX
      or  rax, 0x20000; //set bit 18 (AM)
      mov cr0, rax; //copy flags back
}
Run Code Online (Sandbox Code Playgroud)

第一条指令

mov rax, cr0;
Run Code Online (Sandbox Code Playgroud)

没有特权指令例外.

如何在x64上为我的进程启用对齐异常?

PUSHF

我发现x86有以下指令:

  • PUSHF,POPF …

windows assembly x86-64

23
推荐指数
1
解决办法
1716
查看次数