相关疑难解决方法(0)

x86_64 CPU是否使用相同的缓存行通过共享内存在2个进程之间进行通信?

众所周知,现代x86_64上的所有缓存L1 / L2 / L3级别都是虚拟索引的,并进行了物理标记。并且所有内核都通过QPI / HyperTransport上的高速缓存一致性协议MOESI / MESIF通过最后一级高速缓存-L3进行通信。

例如,Sandybridge系列CPU具有4至16路高速缓存L3和page_size 4KB,那么这允许在并发进程之间交换数据,并发进程通过共享内存在不同内核上执行。这是可能的,因为高速缓存L3不能同时包含与进程1的页面和与进程2的页面相同的物理内存区域。

这是否意味着每次进程1请求相同的共享内存区域时,进程2会将其页面的缓存行刷新到RAM中,然后进程1加载与页面的缓存行相同的内存区域在process-1的虚拟空间中?真的很慢还是处理器使用了一些优化?

现代的x86_64 CPU是否使用相同的缓存行,而不进行任何刷新,以通过共享内存在具有不同虚拟空间的2个进程之间进行通信?

Sandy Bridge Intel CPU-缓存L3:

  • 8 MB-缓存大小
  • 64 B-缓存行大小
  • 128 K-行(128 K = 8 MB / 64 B)
  • 16路
  • 8 K-路数集(8 K = 128 K线/ 16路)
  • 虚拟地址(索引)的13位[18:6]-定义当前设置号(这是标签)
  • 512 K-每个相同(虚拟地址/ 512 K)竞争同一组(8 MB / 16路)
  • 低19位-对确定当前设置的数字有效

  • 4 KB-标准页面大小

  • 仅低12位-每个地址的虚拟和物理地址相同

我们有7个丢失的位[18:12]-即我们需要检查(7 ^ 2 * 16位)= 1024个缓存行。这与1024路缓存相同-因此非常慢。这是否意味着缓存L3(已物理索引,已物理标记)?

标签虚拟地址中丢失位的摘要(页面大小8 KB-12位):

  • L3(8 MB = 64 B x 128 K线),16路,8 K集,13位标签[18:6]-缺少7位
  • L2(256 KB = 64 B x 4 …

concurrency x86 multithreading x86-64 cpu-cache

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

x86-64:缓存加载和逐出指令

对于x86-64架构,是否有一条指令可以将给定内存地址的数据加载到缓存中?类似地,是否存在可以在给定与该高速缓存行对应的存储器地址(或类似高速缓存行标识符)的情况下逐出高速缓存行的指令?

x86 assembly x86-64

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

通过 x86-64 汇编程序进行管道传输时的竞争条件

我编写了以下简化的cat汇编实现。它使用 linux 系统调用,因为我正在运行 linux。这是代码:

.section .data
.set MAX_READ_BYTES, 0xffff

.section .text
.globl _start

_start:
    movq (%rsp), %r10 # save the value of argc somewhere else
    movq 16(%rsp), %r9 # save the value of argv[1] somewhere else

    movl $12, %eax # syscall 12 is brk. see brk(2)
    xorq %rdi, %rdi # call with 0 as first arg to get current end of memory
    syscall
    movq %rax, %r8 # this is the address of the current end of memory

    leaq …
Run Code Online (Sandbox Code Playgroud)

linux assembly x86-64 pipe system-calls

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

使用 Numba 对 2 个矩阵求和的最快方法是什么?

我试图找到使用 Numba 对两个相同大小的矩阵求和的最快方法。我想出了 3 种不同的方法,但没有一种能打败 Numpy。这是我的代码:

import numpy as np
from numba import njit,vectorize, prange,float64
import timeit
import time

# function 1: 
def sum_numpy(A,B):
    return A+B

# function 2: 
sum_numba_simple= njit(cache=True,fastmath=True) (sum_numpy)

# function 3: 
@vectorize([float64(float64, float64)])
def sum_numba_vectorized(A,B):
    return A+B

# function 4: 
@njit('(float64[:,:],float64[:,:])', cache=True, fastmath=True, parallel=True)
def sum_numba_loop(A,B):
    n=A.shape[0]
    m=A.shape[1]
    C = np.empty((n, m), A.dtype)

    for i in prange(n):
        for j in prange(m):
            C[i,j]=A[i,j]+B[i,j]
  
    return C

#Test the functions with 2 matrices of size 1,000,000x3:
N=1000000
np.random.seed(123)
A=np.random.uniform(low=-10, …
Run Code Online (Sandbox Code Playgroud)

performance time multithreading numpy numba

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

“64 位操作系统”、“基于 x64 的处理器”与字长有什么关系?

我想知道,64 位操作系统和基于 x64 的处理器是否意味着字大小(即处理器和物理内存之间的内存传输大小)是 64 位?如果操作系统是 32 位且处理器为 x64 呢?那么基于 x86 的处理器呢?这两个规范(XX 位操作系统和基于 xXX 的处理器)与硬件中的实际字长有什么关系?

64-bit operating-system 32-bit x86-64 cpu-architecture

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

如果 C 是行优先顺序,为什么 ARM 内在代码采用列优先顺序?

我不确定问这个问题的最佳地点在哪里,但我目前正在使用 ARM 内在函数并遵循本指南:https : //developer.arm.com/documentation/102467/0100/Matrix-multiplication-example

但是,那里编写的代码假设数组是按列优先顺序存储的。我一直认为 C 数组是按行优先存储的。他们为什么要这样假设?

编辑:例如,如果不是这样:

void matrix_multiply_c(float32_t *A, float32_t *B, float32_t *C, uint32_t n, uint32_t m, uint32_t k) {
    for (int i_idx=0; i_idx < n; i_idx++) {
        for (int j_idx=0; j_idx < m; j_idx++) {
            for (int k_idx=0; k_idx < k; k_idx++) {
                C[n*j_idx + i_idx] += A[n*k_idx + i_idx]*B[k*j_idx + k_idx];
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

他们这样做了:

void matrix_multiply_c(float32_t *A, float32_t *B, float32_t *C, uint32_t n, uint32_t m, uint32_t k) {
    for (int i_idx=0; i_idx …
Run Code Online (Sandbox Code Playgroud)

c optimization matrix-multiplication neon row-major-order

0
推荐指数
1
解决办法
92
查看次数