在谈论时,有两种方式使用Vectorized
numpy,但并不总是清楚这是什么意思。
- 对数组的所有元素进行运算的运算
- 在内部调用优化的(在许多情况下为多线程)数字代码的操作
第二点是使向量化操作比python中的for循环快得多的原因,而多线程部分是使向量化操作比列表理解要快的原因。当这里的评论者指出矢量化代码更快时,他们也指的是第二种情况。但是,在numpy文档中,矢量化仅指第一种情况。这意味着您可以直接在数组上使用函数,而不必遍历所有元素并在每个元素上调用它。从这个意义上讲,它使代码更简洁,但不一定更快。一些矢量化操作确实会调用多线程代码,但据我所知,这仅限于线性代数例程。就个人而言,我更喜欢使用向量化运算,因为即使性能相同,我也认为它比列表理解更具可读性。
现在,对于有问题的代码,其文档
np.char(是的别名
np.core.defchararray)指出
的
chararray存在是为了与Numarray向后兼容类,所以不推荐在新的发展。从numpy
1.4开始,如果需要字符串数组,建议使用dtypeobject_,string_或数组unipre_,并使用numpy.char模块中的free函数进行快速矢量化字符串操作。
因此,有四种方法(不建议一种)来处理numpy中的字符串。必须进行一些测试,因为肯定每种方法都会有不同的优缺点。使用定义如下的数组:
npob = np.array(milstr, dtype=np.object_)npuni = np.array(milstr, dtype=np.unipre_)npstr = np.array(milstr, dtype=np.string_)npchar = npstr.view(np.chararray)npcharU = npuni.view(np.chararray)
这将创建具有以下数据类型的数组(或后两个字符数组):
In [68]: npob.dtypeOut[68]: dtype('O')In [69]: npuni.dtypeOut[69]: dtype('<U10')In [70]: npstr.dtypeOut[70]: dtype('S10')In [71]: npchar.dtypeOut[71]: dtype('S10')In [72]: npcharU.dtypeOut[72]: dtype('<U10')基准测试在这些数据类型上提供了相当范围的性能:
%timeit [x.upper() for x in test]%timeit np.char.upper(test)# test = milstr103 ms ± 1.42 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)377 ms ± 3.67 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)# test = npob110 ms ± 659 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)<error on second test, vectorized operations don't work with object arrays># test = npuni295 ms ± 1.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)323 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)# test = npstr125 ms ± 2.52 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)125 ms ± 483 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)# test = npchar663 ms ± 4.94 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)127 ms ± 1.27 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)# test = npcharU887 ms ± 8.13 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)325 ms ± 3.23 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
令人惊讶的是,使用普通的旧字符串列表仍然是最快的。当数据类型为
string_或时
object_,Numpy具有竞争力,但是一旦包含unipre,性能就会变得差很多。
chararray到目前为止,无论是否处理unipre,它都是最慢的。应该清楚为什么不建议使用它。
使用unipre字符串会严重影响性能。该文档的状态为这些类型之间的差异以下
为了与Python
2向后兼容,Sand和atypestrings保留以零结尾的字节,并且np.string_继续映射到np.bytes_。要在Python
3中使用实际的字符串,请使用U或np.unipre_。对于不需要零终止的带符号字节,可以使用b或i1。
在这种情况下,如果字符集不需要unipre,则可以使用更快的
string_类型。如果需要unipre,则可以通过使用列表或使用numpy类型的数组(
object_如果需要其他numpy功能)来获得更好的性能。列表何时可能更好的另一个很好的例子是附加大量数据
因此,请注意以下几点:
- Python虽然被普遍认为是缓慢的,但在某些常见的事情上却表现出色。Numpy通常相当快,但并未针对所有内容进行优化。
- 阅读文档。如果做事的方法不只一种(通常是这样),那么对您尝试做的事情来说,一种可能性更好。
- 不要盲目地认为矢量化代码会更快-在关注性能时始终进行概要分析(适用于所有“优化”技巧)。



