相关疑难解决方法(0)

如果32位整数溢出,我们可以使用40位结构而不是64位长结构吗?

例如,如果一个32位整数溢出,而不是升级intlong,如果我们需要一个仅在2 40之内的范围,我们可以使用一些40位类型,这样我们就可以节省24(64-40)位整数?

如果是这样,怎么样?

我必须处理数十亿和空间是一个更大的约束.

c c++ memory-management integer-overflow

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

为什么允许gcc从结构中推测性地加载?

显示可能出错的gcc优化和用户代码的示例

下面的代码段中的函数'foo'将只加载一个结构成员A或B; 至少这是未经优化的代码的意图.

typedef struct {
  int A;
  int B;
} Pair;

int foo(const Pair *P, int c) {
  int x;
  if (c)
    x = P->A;
  else
    x = P->B;
  return c/102 + x;
}
Run Code Online (Sandbox Code Playgroud)

这是gcc -O3给出的:

mov eax, esi
mov edx, -1600085855
test esi, esi
mov ecx, DWORD PTR [rdi+4]   <-- ***load P->B**
cmovne ecx, DWORD PTR [rdi]  <-- ***load P->A***
imul edx
lea eax, [rdx+rsi]
sar esi, 31
sar eax, 6
sub eax, esi
add eax, ecx
ret …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly gcc compiler-optimization

52
推荐指数
5
解决办法
4140
查看次数

现代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
查看次数

为什么从多个线程使用相同的缓存行不会导致严重的减速?

看看这个片段:

#include <atomic>
#include <thread>

typedef volatile unsigned char Type;
// typedef std::atomic_uchar Type;

void fn(Type *p) {
    for (int i=0; i<500000000; i++) {
        (*p)++;
    }
}

int main() {
    const int N = 4;

    std::thread thr[N];
    alignas(64) Type buffer[N*64];

    for (int i=0; i<N; i++) {
        thr[i] = std::thread(&fn, &buffer[i*1]);
    }

    for (int i=0; i<N; i++) {
        thr[i].join();
    }

}
Run Code Online (Sandbox Code Playgroud)

这个小程序从四个不同的线程中多次增加四个相邻的字节.在此之前,我使用了以下规则:不要使用来自不同线程的相同缓存行,因为缓存线共享不好.所以我期望四线程版本(N=4)比一个线程版本(N=1)慢得多.

但是,这些是我的测量结果(在Haswell CPU上):

  • N = 1:1秒
  • N = 4:1.2秒

所以N=4速度并不慢.如果我使用不同的缓存行(替换*1*64),则会 …

c++ performance x86 multithreading

21
推荐指数
1
解决办法
1168
查看次数

在64位机器上,我可以安全地并行操作64位四字的单个字节吗?

背景

我正在对图像中的行和列进行并行操作.我的图像是8位或16位像素,我在64位机器上.当我对并行的列进行操作时,两个相邻的列可以共享相同的32位int或64位long.基本上,我想知道我是否可以安全地并行操作同一个四字的单个字节.

最小的测试

我写了一个我无法失败的最小测试函数.对于64位中的每个字节long,我同时在有限的有序域中执行连续的乘法p.我知道费马的小定理 a^(p-1) = 1 mod p何时p是素数.我改变了值ap我的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

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

修改数组中的一个元素而另一个线程修改同一个数组的另一个元素时,它是定义良好的行为吗?

给定类型的阵列foo_t[n]和一组Ñ线程,其中每一个的Ñ线程读取和修改阵列的不同元件,我需要显式同步阵列的修改或我可以假设,同时变更部件的阵列是定义明确的行为?它有多大foo_t/哪个对齐有关系?

c synchronization pthreads undefined-behavior

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