相关疑难解决方法(0)

为memcpy增强了REP MOVSB

我想使用增强的REP MOVSB(ERMSB)为自定义获得高带宽memcpy.

ERMSB引入了Ivy Bridge微体系结构.如果您不知道ERMSB是什么,请参阅英特尔优化手册中的"增强型REP MOVSB和STOSB操作(ERMSB)" 部分.

我知道直接执行此操作的唯一方法是使用内联汇编.我从https://groups.google.com/forum/#!topic/gnu.gcc.help/-Bmlm_EG_fE获得了以下功能

static inline void *__movsb(void *d, const void *s, size_t n) {
  asm volatile ("rep movsb"
                : "=D" (d),
                  "=S" (s),
                  "=c" (n)
                : "0" (d),
                  "1" (s),
                  "2" (n)
                : "memory");
  return d;
}
Run Code Online (Sandbox Code Playgroud)

然而,当我使用它时,带宽远小于memcpy. 使用我的i7-6700HQ(Skylake)系统,Ubuntu 16.10,DDR4 @ 2400 MHz双通道32 GB,GCC 6.2,__movsb获得15 GB/s并memcpy获得26 GB/s.

为什么带宽如此低REP MOVSB?我该怎么做才能改善它?

这是我用来测试它的代码.

//gcc -O3 -march=native -fopenmp foo.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly gcc memcpy

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

Java 8 Unsafe:xxxFence()指令

在Java 8中,三个内存屏障指令被添加到Unsafe类():

/**
 * Ensures lack of reordering of loads before the fence
 * with loads or stores after the fence.
 */
void loadFence();

/**
 * Ensures lack of reordering of stores before the fence
 * with loads or stores after the fence.
 */
void storeFence();

/**
 * Ensures lack of reordering of loads or stores before the fence
 * with loads or stores after the fence.
 */
void fullFence();
Run Code Online (Sandbox Code Playgroud)

如果我们用以下方式定义内存屏障(我认为或多或少容易理解):

考虑X和Y是要重新排序的操作类型/类,

X_YFence() 是一个内存屏障指令,它确保在屏障启动之后,在屏障完成任何操作之前,屏障之前的所有类型X操作都已完成.

我们现在可以将障碍名称"映射" Unsafe …

java concurrency unsafe memory-fences java-8

45
推荐指数
3
解决办法
5720
查看次数

什么时候需要x86 LFENCE,SFENCE和MFENCE指令?

好吧,我已经从SO关于x86处理器围栏阅读下列适量(LFENCE,SFENCEMFENCE):

和:

而且我必须说实话,我还不能确定何时需要围栏.我试图从删除完全锁定并尝试通过栅栏使用更细粒度的锁定的角度来理解,以最小化延迟延迟.

首先,这是我不明白的两个具体问题:

有时在进行存储时,CPU会写入其存储缓冲区而不是L1缓存.但是,我不了解CPU执行此操作的条款?

CPU2可能希望加载已写入CPU1的存储缓冲区的值.据我了解,问题是CPU2无法在CPU1的存储缓冲区中看到新值.为什么MESI协议不能将刷新存储缓冲区作为其协议的一部分?

更一般地,可以请人试图描述的总体方案,并帮助时解释LFENCE/ MFENCESFENCE被需要的指令?

NB阅读本主题的一个问题是,当我只对Intel x86-64架构感兴趣时,"通常"为多CPU架构编写的文章数量.

cpu x86 assembly multithreading memory-fences

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

哪个是x86上更好的写屏障:lock + addl还是xchgl?

Linux内核lock; addl $0,0(%%esp)用作写屏障,而RE2库xchgl (%0),%0用作写屏障.有什么区别,哪个更好?

x86还需要读屏障指令吗?RE2将其读屏障功能定义为x86上的无操作,而Linux lfence根据SSE2是否可用将其定义为无操作或无操作.什么时候lfence需要?

x86 assembly memory-barriers

23
推荐指数
4
解决办法
7771
查看次数

英特尔内存模型是否使SFENCE和LFENCE冗余?

英特尔内存模型保证:

  • 商店不会与其他商店重新订购
  • 载荷不会与其他载荷重新订购

http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/

我已经看到声称由于Intel内存模型,SFENCE在x86-64上是多余的,但从来没有LFENCE.上述内存模型规则是否使指令冗余?

optimization x86 assembly atomic memory-barriers

15
推荐指数
1
解决办法
1355
查看次数

C11 Atomic Acquire/Release 和 x86_64 缺乏加载/存储一致性?

我正在努力处理 C11 标准的第 5.1.2.4 节,特别是发布/获取的语义。我注意到https://preshing.com/20120913/acquire-and-release-semantics/(以及其他)指出:

... 释放语义防止写入释放的内存重新排序与程序顺序之前的任何读取或写入操作。

因此,对于以下情况:

typedef struct test_struct
{
  _Atomic(bool) ready ;
  int  v1 ;
  int  v2 ;
} test_struct_t ;

extern void
test_init(test_struct_t* ts, int v1, int v2)
{
  ts->v1 = v1 ;
  ts->v2 = v2 ;
  atomic_store_explicit(&ts->ready, false, memory_order_release) ;
}

extern int
test_thread_1(test_struct_t* ts, int v2)
{
  int v1 ;
  while (atomic_load_explicit(&ts->ready, memory_order_acquire)) ;
  ts->v2 = v2 ;       // expect read to happen before store/release 
  v1     = ts->v1 ;   // expect write …
Run Code Online (Sandbox Code Playgroud)

c x86-64 memory-model memory-barriers stdatomic

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

无锁队列的C代码

我怎么能实现这个无锁队列伪代码C

ENQUEUE(x)
    q ? new record
    q^.value ? x
    q^.next ? NULL
    repeat
        p ? tail
        succ ? COMPARE&SWAP(p^.next, NULL, q)
        if succ ? TRUE
            COMPARE&SWAP(tail, p, p^.next)
    until succ = TRUE
    COMPARE&SWAP(tail,p,q)
end

DEQUEUE()
    repeat
        p ? head
        if p^.next = NULL
            error queue empty
    until COMPARE&SWAP(head, p, p^.next)
    return p^.next^.value
end
Run Code Online (Sandbox Code Playgroud)

如何使用内置函数进行原子内存访问

__sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
Run Code Online (Sandbox Code Playgroud)

我现在有

typedef struct queueelem {
    queuedata_t data;
    struct queueelem *next;
} queueelem_t;

typedef struct queue …
Run Code Online (Sandbox Code Playgroud)

c queue lock-free

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

C++"记忆障碍"的例子

我正在阅读关于volatile关键字的这个问题的答案:

/sf/answers/173962421/

这个人说:

防止重新排序的解决方案是使用内存屏障,该内存屏障向编译器和CPU指示在该点上不能重新排序内存访问.在易失性变量访问周围放置这些障碍可确保即使非易失性访问也不会在易失性访问中重新排序,从而允许我们编写线程安全的代码.

但是,内存障碍还可以确保在达到屏障时执行所有挂起的读/写操作,因此它有效地为我们提供了我们自己需要的所有内容,从而使得volatile不必要.我们可以完全删除volatile限定符.

这个"内存障碍"在C++中是如何实现的?

编辑:

有人可以给出一个简单的代码示例吗?

c++ multithreading volatile

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

此信封实现是否正确使用C ++ 11原子?

我编写了一个简单的“信封”类,以确保我正确理解C ++ 11原子语义。我有一个标头和一个有效负载,编写器清除该标头,填充有效负载,然后用递增的整数填充标头。这样的想法是,读取器然后可以读取标头,将有效负载换出,再次读取标头,如果标头相同,则读取器可以假定他们成功复制了有效负载。读者可能会错过一些更新是可以的,但是让他们获得更新的撕裂(其中来自不同更新的字节混合在一起)也不是可以的。永远只有一个读者和一个作家。

编写者使用释放内存顺序,而读者使用获取内存顺序。

是否存在通过原子存储/加载调用对memcpy重新排序的风险?还是可以将负载彼此重新排序?这永远不会让我流产,但也许我很幸运。

#include <iostream>
#include <atomic>
#include <thread>
#include <cstring>

struct envelope {
    alignas(64) uint64_t writer_sequence_number = 1;
    std::atomic<uint64_t> sequence_number;
    char payload[5000];

    void start_writing()
    {
        sequence_number.store(0, std::memory_order::memory_order_release);
    }

    void publish()
    {
        sequence_number.store(++writer_sequence_number, std::memory_order::memory_order_release);
    }

    bool try_copy(char* copy)
    {
        auto before = sequence_number.load(std::memory_order::memory_order_acquire);
        if(!before) {
            return false;
        }
        ::memcpy(copy, payload, 5000);
        auto after = sequence_number.load(std::memory_order::memory_order_acquire);
        return before == after;
    }
};

envelope g_envelope;

void reader_thread()
{
    char local_copy[5000];
    unsigned messages_received = 0;
    while(true) {
        if(g_envelope.try_copy(local_copy)) {
            for(int i …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading memory-model thread-safety stdatomic

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

加载和存储是否只有重新排序的指令?

我已经阅读了很多关于内存排序的文章,并且所有这些文章都只说CPU重新加载和存储.

CPU(我对x86 CPU特别感兴趣)是否仅重新排序加载和存储,并且不重新排序它具有的其余指令?

x86 cpu-architecture memory-barriers

6
推荐指数
2
解决办法
915
查看次数