这篇文章是通过讨论单元数组是否为"正常数组"并且向量化不适用于单元数组来触发的.
我想知道为什么在MATLAB中没有实现后面的矢量化语法,它反对它:
>> {'hallo','matlab','world'} == 'matlab'
??? Undefined function or method 'eq' for input arguments of type 'cell'.
Run Code Online (Sandbox Code Playgroud)
在内部它将等同于
[{'hallo'},{'matlab'},{'world'}] == {'matlab'}
Run Code Online (Sandbox Code Playgroud)
因为MATLAB知道何时投射,以下工作:
[{'hallo','matlab'},'world']
Run Code Online (Sandbox Code Playgroud)
Cell数组是一个指针数组.如果左侧和右侧都指向相同的对象,isequal('hallo','hallo')则按预期返回true,那么为什么MATLAB仍然不允许最顶层的示例?
我知道我可以使用strmatch或cellfun.
摘要:
==这是需要向量化在上面的例子中是eq与不isequal(其它运营商<是lt等)eq 内置数值类型,适用于所有其他类型(如字符串)MATLAB提供了重载此(和其他)运算符的自由.myFun( myString )或的函数矢量化myFun( myCellOfStrings )也是可能的,你只需在内部实现它myFun.功能sin(val)和sin(array)工作也不是巫术,而是因为这两种情况都是在内部实施的.以下代码最能说明我的问题:
输出到控制台(NB甚至第一次测试需要大约8分钟)显示512x512x512x16位阵列分配消耗不超过预期(每个256MByte),并且查看"顶部"过程通常仍然是600MByte如预期.
但是,在调用函数的矢量化版本时,该过程会扩展到巨大的大小(超过7GByte!).即便是我能想到的最明显的解释 - 向量化将输入和输出转换为内部的float64 - 即使向量化函数返回一个int16,也只能占用几千兆字节,返回的数组肯定是一个int16.有没有办法避免这种情况发生?我使用/理解vectorize的otypes参数错了吗?
import numpy as np
import subprocess
def logmem():
subprocess.call('cat /proc/meminfo | grep MemFree',shell=True)
def fn(x):
return np.int16(x*x)
def test_plain(v):
print "Explicit looping:"
logmem()
r=np.zeros(v.shape,dtype=np.int16)
for z in xrange(v.shape[0]):
for y in xrange(v.shape[1]):
for x in xrange(v.shape[2]):
r[z,y,x]=fn(x)
print type(r[0,0,0])
logmem()
return r
vecfn=np.vectorize(fn,otypes=[np.int16])
def test_vectorize(v):
print "Vectorize:"
logmem()
r=vecfn(v)
print type(r[0,0,0])
logmem()
return r
logmem()
s=(512,512,512)
v=np.ones(s,dtype=np.int16)
logmem()
test_plain(v)
test_vectorize(v)
v=None
logmem()
Run Code Online (Sandbox Code Playgroud)
我正在使用amd64 Debian Squeeze系统(Python 2.6.6,numpy 1.4.1)中最新的Python/numpy版本.
我正在使用以下命令编译我的代码:
gcc -O3 -ftree-vectorizer-verbose=6 -msse4.1 -ffast-math
Run Code Online (Sandbox Code Playgroud)
有了这个,所有的优化都被启用了.
但我想在保持其他优化的同时禁用矢量化.
我有一个MATLAB例程,有一个相当明显的瓶颈.我已经分析了这个函数,结果是在函数中使用了2/3的计算时间levels:

该函数levels采用浮点矩阵并将每列拆分为nLevels桶,返回与输入大小相同的矩阵,每个条目替换为它所属的桶的数量.
为此,我使用该quantile函数获取存储区限制,并使用循环将条目分配给存储区.这是我的实现:
function [Y q] = levels(X,nLevels)
% "Assign each of the elements of X to an integer-valued level"
p = linspace(0, 1.0, nLevels+1);
q = quantile(X,p);
if isvector(q)
q=transpose(q);
end
Y = zeros(size(X));
for i = 1:nLevels
% "The variables g and l indicate the entries that are respectively greater than
% or less than the relevant bucket limits. The line Y(g & l) = i is assigning the
% …Run Code Online (Sandbox Code Playgroud) 我有一个矢量化函数,它计算到一大组点的距离.为了提高性能,我通过仅选择必要的数量来限制点数.而不是distanceToPoint(points.x)我使用distanceToPoint(points.x(IDX)).当我绘制所需的计算时间时,我可以看到,当索引部分超过数据的%75时,它实际上需要更多的时间.我该怎么做才能克服这个问题,或者将性能提升推到%85?

编辑:我在切换到逻辑索引后添加结果,显然更好.似乎在低%10端有性能损失(如果您在彼此之上查看图像,则可见)

我有2 x 4和3 x 4的矩阵.我想找到跨行的欧几里德距离,最后得到一个2 x 3矩阵.这是带有一个for循环的代码,它计算针对所有b行向量中每个行向量的欧氏距离.如何在不使用for循环的情况下执行相同的操作?
import numpy as np
a = np.array([[1,1,1,1],[2,2,2,2]])
b = np.array([[1,2,3,4],[1,1,1,1],[1,2,1,9]])
dists = np.zeros((2, 3))
for i in range(2):
dists[i] = np.sqrt(np.sum(np.square(a[i] - b), axis=1))
Run Code Online (Sandbox Code Playgroud) 我正在矢量化一段代码,在某些时候我有以下设置:
register m128 a = { 99,99,99,99,99,99,99,99 }
register m128 b = { 100,50,119,30,99,40,50,20 }
Run Code Online (Sandbox Code Playgroud)
我目前正在short这些寄存器中打包,这就是为什么每个寄存器有8个值.如果第i个值大于或等于(在这种情况下,用常数99填充),我想要做的是b用相应的值减去第i个元素.为此,我首先在和之间使用大于或等于的操作,这产生了这个例子:abaaba
register m128 c = { 1,0,1,0,1,0,0,0 }
Run Code Online (Sandbox Code Playgroud)
为了完成操作,我想使用乘法和减法,即存储在b操作中b -= a*c.结果将是:
b = { 1,50,20,30,0,40,50,20 }
Run Code Online (Sandbox Code Playgroud)
有没有做这种事的操作?我发现的是Haswell的融合操作,但我目前正在研究Sandy-Bridge.此外,如果有人有更好的想法这样做,请告诉我(例如我可以做一个逻辑减法:如果1 c然后我减去,否则没有.
我是OpenMP的新手,我正在尝试使用OpenMP对代码进行并行化:
#pragma omp parallel for
for(int k=0;k<m;k++)
{
for(int j=n-1;j>=0;j--)
{
outX[k+j*m] = inB2[j+n * k] / inA2[j*n + j];
for(int i=0;i<j;i++)
{
inB2[k*n+i] -= inA2[i+n * j] * outX[k + m*j];
}
}
}
Run Code Online (Sandbox Code Playgroud)
对外循环进行并行化非常简单,但为了优化它,我想要对最内循环(对i进行迭代)进行并行化.但是当我尝试这样做时:
#pragma omp parallel for
for(int i=0;i<j;i++)
{
inB2[k*n+i] -= inA2[i+n * j] * outX[k + m*j];
}
Run Code Online (Sandbox Code Playgroud)
编译器不会对内循环进行矢量化("因为可能的别名而导致为矢量化而循环"),这使得它运行得更慢.我用它编译了它gcc -ffast-math -std=c++11 -fopenmp -O3 -msse2 -funroll-loops -g -fopt-info-vec prog.cpp
谢谢你的建议!
编辑:我正在使用__restrict关键字的数组.
EDIT2:有趣的是,当我在内循环中仅保留pragma并将其从外部移除时,gcc将向量化它.因此,当我尝试对两个周期进行并行化时,问题才会发生.
编辑3:当我使用#pragma omp parallel for simd时,编译器将向量化循环.但它仍然比没有内部循环并行化更慢.
如何1有效地设置AVX2
N位N位的__m256i,其余的设置0?
当范围可以在__m256i值的中间开始和结束时,这些是针对位范围的尾部和头部的2个单独的操作.占据全部__m256i值的范围部分使用全部0或全部1掩模进行处理.
我发现,numpy.vectorize允许将希望将单个数字作为输入的“普通”函数转换为函数,该函数也可以将输入列表转换为该函数已映射到每个输入的列表。例如,以下测试通过:
import numpy as np
import pytest
@np.vectorize
def f(x):
if x == 0:
return 1
else:
return 2
def test_1():
assert list(f([0, 1, 2])) == [1, 2, 2]
def test_2():
assert f(0) == 1
if __name__ == "__main__":
pytest.main([__file__])
Run Code Online (Sandbox Code Playgroud)
但是,我无法使它用于使用实例属性的实例方法。例如:
class Dummy(object):
def __init__(self, val=1):
self.val = val
@np.vectorize
def f(self, x):
if x == 0:
return self.val
else:
return 2
def test_3():
assert list(Dummy().f([0, 1, 2])) == [1, 2, 2]
Run Code Online (Sandbox Code Playgroud)
该测试失败:
=================================== FAILURES ===================================
____________________________________ test_3 …Run Code Online (Sandbox Code Playgroud)