曾几何时,为了编写x86汇编程序,你会得到一条说明"加载EDX寄存器的值为5","递增EDX"寄存器等的指令.
对于具有4个核心(甚至更多)的现代CPU,在机器代码级别上它看起来就像有4个独立的CPU(即只有4个不同的"EDX"寄存器)?如果是这样,当你说"递增EDX寄存器"时,是什么决定了哪个CPU的EDX寄存器递增?现在x86汇编程序中是否存在"CPU上下文"或"线程"概念?
核心之间的通信/同步如何工作?
如果您正在编写操作系统,那么通过硬件公开哪种机制可以让您在不同的内核上安排执行?这是一些特殊的特权指示吗?
如果您正在为多核CPU编写优化编译器/字节码VM,那么您需要具体了解x86,以使其生成能够在所有内核中高效运行的代码?
对x86机器代码进行了哪些更改以支持多核功能?
在学习"汇编语言"(在使用GNU作为汇编程序的x86架构上的linux中)时,其中一个时刻就是使用系统调用的可能性.这些系统调用非常方便,有时甚至是必需的,因为您的程序在用户空间中运行.
然而,系统调用在性能方面相当昂贵,因为它们需要中断(当然还有系统调用),这意味着必须从用户空间中的当前活动程序到内核空间中运行的系统进行上下文切换.
我想说的是:我目前正在实现一个编译器(用于大学项目),我想要添加的一个额外功能是支持多线程代码以提高编译程序的性能.因为一些多线程代码将由编译器本身自动生成,所以这几乎可以保证其中也会有很少的多线程代码.为了获得性能,我必须确保使用线程可以实现这一点.
但我担心的是,为了使用线程,我必须进行系统调用和必要的中断.因此,微小的(自动生成的)线程将受到进行这些系统调用所花费的时间的极大影响,这甚至可能导致性能损失......
因此,我的问题是双重的(在其下面有一个额外的奖励问题):
我的猜测是没有系统调用就不可能有多线程汇编程序代码.即使是这种情况,您是否有建议(甚至更好:一些实际代码)尽可能高效地实现线程?
假设我有一个如下定义的数组:
volatile char v[2];
Run Code Online (Sandbox Code Playgroud)
我有两个线程(分别用A,B表示)操作数组v.如果我确保A,B在任何时候使用不同的索引,也就是说,如果A现在正在操纵v[i],那么B要么什么都不做,要么操纵v[1-i].我想知道这种情况需要同步吗?
我已经提到了这个问题,但我认为它在Java中是有限的.我之所以提出这个问题的原因是,我在一个大型项目中一直在努力解决一个奇怪而罕见的错误,直到现在,我能解释这个错误的唯一原因是需要同步以上操纵.(由于这个bug非常罕见,我很难证明我的推测是否属实)
编辑:可以读取和修改v.
我正在对图像中的行和列进行并行操作.我的图像是8位或16位像素,我在64位机器上.当我对并行的列进行操作时,两个相邻的列可以共享相同的32位int或64位long.基本上,我想知道我是否可以安全地并行操作同一个四字的单个字节.
我写了一个我无法失败的最小测试函数.对于64位中的每个字节long,我同时在有限的有序域中执行连续的乘法p.我知道费马的小定理 a^(p-1) = 1 mod p何时p是素数.我改变了值a和p我的8个线程中的每一个,并执行k*(p-1)乘法运算a.当线程完成每个字节应该是1.事实上,我的测试用例通过了.每次运行时,我都会得到以下输出:
8
101010101010101
101010101010101
我的系统是Linux 4.13.0-041300-generic x86_64,带有8核Intel(R)Core(TM)i7-7700HQ CPU @ 2.80GHz.我用g ++ 7.2.0 -O2编译并检查了程序集.我添加了"INNER LOOP"的程序集并对其进行了评论.在我看来,生成的代码是安全的,因为存储只是将低8位写入目标而不是进行一些按位算术并存储到整个字或四字.g ++ -O3生成了类似的代码.
我想知道这段代码是否始终是线程安全的,如果没有,它将在什么条件下不会.也许我是非常偏执,但我觉得我需要一次操作四字,以确保安全.
#include <iostream>
#include <pthread.h>
class FermatLTParams
{
public:
FermatLTParams(unsigned char *_dst, unsigned int _p, unsigned int _a, unsigned int _k)
: dst(_dst), p(_p), a(_a), k(_k) {}
unsigned char …Run Code Online (Sandbox Code Playgroud) c++ parallel-processing multithreading x86-64 image-processing
根据CERT编码规则POS49-C,访问相同结构的不同字段的不同线程可能会发生冲突.
我使用常规的unsigned int而不是bit-field.
struct multi_threaded_flags {
unsigned int flag1;
unsigned int flag2;
};
struct multi_threaded_flags flags;
void thread1(void) {
flags.flag1 = 1;
}
void thread2(void) {
flags.flag2 = 2;
}
Run Code Online (Sandbox Code Playgroud)
我可以看到,即使是unsigned int,仍然可能存在竞争条件IF编译器决定使用加载/存储8个字节而不是4个字节.我认为编译器永远不会这样做,赛车条件永远不会发生在这里,但这完全是我的猜测.
是否有关于此案例的明确定义的汇编/编译器文档?我希望锁定,这是昂贵的,是这种情况恰好未定义的最后手段.
仅供参考,我使用gcc.