以下是相关程序的摘录.矩阵img[][]的大小为SIZE×SIZE,并在以下位置初始化:
img[j][i] = 2 * j + i
然后,你创建一个矩阵res[][],这里的每个字段都是img矩阵中它周围9个字段的平均值.为简单起见,边框保留为0.
for(i=1;i<SIZE-1;i++)
for(j=1;j<SIZE-1;j++) {
res[j][i]=0;
for(k=-1;k<2;k++)
for(l=-1;l<2;l++)
res[j][i] += img[j+l][i+k];
res[j][i] /= 9;
}
Run Code Online (Sandbox Code Playgroud)
这就是该计划的全部内容.为了完整起见,以下是之前的内容.没有代码.如您所见,它只是初始化.
#define SIZE 8192
float img[SIZE][SIZE]; // input image
float res[SIZE][SIZE]; //result of mean filter
int i,j,k,l;
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
img[j][i] = (2*j+i)%8196;
Run Code Online (Sandbox Code Playgroud)
基本上,当SIZE是2048的倍数时,此程序很慢,例如执行时间:
SIZE = 8191: 3.44 secs
SIZE = 8192: 7.20 secs
SIZE = 8193: 3.18 secs
Run Code Online (Sandbox Code Playgroud)
编译器是GCC.据我所知,这是因为内存管理,但我对这个主题并不太了解,这就是我在这里问的原因.
另外如何解决这个问题会很好,但如果有人能够解释这些执行时间,我已经足够开心了.
我已经知道malloc/free了,但问题不在于使用的内存量,它只是执行时间,所以我不知道这会有多大帮助.
我使用英特尔®架构代码分析器(IACA)发现了一些意想不到的东西(对我而言).
以下指令使用[base+index]寻址
addps xmm1, xmmword ptr [rsi+rax*1]
Run Code Online (Sandbox Code Playgroud)
根据IACA没有微熔丝.但是,如果我用[base+offset]这样的
addps xmm1, xmmword ptr [rsi]
Run Code Online (Sandbox Code Playgroud)
IACA报告它确实融合了.
英特尔优化参考手册的第2-11节给出了以下"可以由所有解码器处理的微融合微操作"的示例
FADD DOUBLE PTR [RDI + RSI*8]
Run Code Online (Sandbox Code Playgroud)
和Agner Fog的优化装配手册也给出了使用[base+index]寻址的微操作融合的例子.例如,请参见第12.2节"Core2上的相同示例".那么正确的答案是什么?
我是指令优化的新手.
我对一个简单的函数dotp进行了简单的分析,该函数用于获取两个浮点数组的点积.
C代码如下:
float dotp(
const float x[],
const float y[],
const short n
)
{
short i;
float suma;
suma = 0.0f;
for(i=0; i<n; i++)
{
suma += x[i] * y[i];
}
return suma;
}
Run Code Online (Sandbox Code Playgroud)
我用昂纳雾在网络上提供的测试框架testp.
在这种情况下使用的数组是对齐的:
int n = 2048;
float* z2 = (float*)_mm_malloc(sizeof(float)*n, 64);
char *mem = (char*)_mm_malloc(1<<18,4096);
char *a = mem;
char *b = a+n*sizeof(float);
char *c = b+n*sizeof(float);
float *x = (float*)a;
float *y = (float*)b;
float *z = (float*)c;
Run Code Online (Sandbox Code Playgroud)
然后我调用函数dotp,n = 2048,repeat …
受到最近关于SO的问题和给出的答案的启发,这让我感到非常无知,我决定花一些时间来学习更多有关CPU缓存的知识,并编写了一个小程序来验证我是否正确地完成了这一切(大多数情况下)可能不是,我害怕).我将首先写下构成我期望的假设,所以如果错误的话,你可能会阻止我.基于我所读到的,一般来说:
n三通关联高速缓存被分成s组,每组包含n行,每行具有固定大小L;A可以被映射到任何所述的n的高速缓存行一个集;A映射地址的集合可以通过将地址空间拆分为每个大小为一个高速缓存行A的插槽,然后计算插槽(I = A / L)的索引,最后执行模运算以将索引映射到目标中来找到. set T(T = I % s);我的第一个问题是:这些假设是否正确?
假设它们是,我尝试使用这些概念,所以我实际上可以看到它们对程序产生了具体的影响.我写了一个简单的测试,它分配一个B字节的内存缓冲区,并从缓冲区的开头以固定的给定步长 增量重复访问该缓冲区的位置(意味着如果是14,步骤是3,我只重复访问位置0 ,3,6,9和12 - 如果是13,14或15 ,则同样如此:BB
int index = 0;
for (int i = 0; i < REPS; i++) …Run Code Online (Sandbox Code Playgroud) 考虑以下功能:
def f(x, dummy=list(range(10000000))):
return x
Run Code Online (Sandbox Code Playgroud)
如果我使用multiprocessing.Pool.imap,我会得到以下时间:
import time
import os
from multiprocessing import Pool
def f(x, dummy=list(range(10000000))):
return x
start = time.time()
pool = Pool(2)
for x in pool.imap(f, range(10)):
print("parent process, x=%s, elapsed=%s" % (x, int(time.time() - start)))
parent process, x=0, elapsed=0
parent process, x=1, elapsed=0
parent process, x=2, elapsed=0
parent process, x=3, elapsed=0
parent process, x=4, elapsed=0
parent process, x=5, elapsed=0
parent process, x=6, elapsed=0
parent process, x=7, elapsed=0
parent process, x=8, elapsed=0
parent process, …Run Code Online (Sandbox Code Playgroud) 有人可以告诉我为什么这个Python Numpy代码:
import numpy as np
import time
k_max = 40000
N = 10000
data = np.zeros((2,N))
coefs = np.zeros((k_max,2),dtype=float)
t1 = time.time()
for k in xrange(1,k_max+1):
cos_k = np.cos(k*data[0,:])
sin_k = np.sin(k*data[0,:])
coefs[k-1,0] = (data[1,-1]-data[1,0]) + np.sum(data[1,:-1]*(cos_k[:-1] - cos_k[1:]))
coefs[k-1,1] = np.sum(data[1,:-1]*(sin_k[:-1] - sin_k[1:]))
t2 = time.time()
print('Time:')
print(t2-t1)
Run Code Online (Sandbox Code Playgroud)
比这个C++代码更快:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <time.h>
using namespace std;
// consts
const unsigned int k_max = 40000;
const unsigned int N = 10000;
int main()
{
time_t …Run Code Online (Sandbox Code Playgroud)