28

だから私はいくつかのテストを行い、奇妙な結果を得ました。

コード:

import numpy as np
import timeit


setup = """
import numpy as np
A = np.ones((1000,1000,3), dtype=datatype)
"""

datatypes = "np.uint8", "np.uint16", "np.uint32", "np.uint64",  "np.float16", "np.float32", "np.float64"

stmt1 = """
A = A * 255
A = A / 255
A = A - 1
A = A + 1
"""
#~ np.uint8 : 1.04969205993
#~ np.uint16 : 1.19391073202
#~ np.uint32 : 1.37279821351
#~ np.uint64 : 2.99286961148
#~ np.float16 : 9.62375889588
#~ np.float32 : 0.884994368045
#~ np.float64 : 0.920502625252

stmt2 = """
A *= 255
A /= 255
A -= 1
A += 1
"""
#~ np.uint8 : 0.959514497259
#~ np.uint16 : 0.988570167659
#~ np.uint32 : 0.963571471946
#~ np.uint64 : 2.07768933333
#~ np.float16 : 9.40085450056
#~ np.float32 : 0.882363984225
#~ np.float64 : 0.910147440048

stmt3 = """
A = A * 255 / 255 - 1 + 1
"""
#~ np.uint8 : 1.05919667881
#~ np.uint16 : 1.20249978404
#~ np.uint32 : 1.58037744789
#~ np.uint64 : 3.47520357571
#~ np.float16 : 10.4792515701
#~ np.float32 : 1.29654744484
#~ np.float64 : 1.80735079168

stmt4 = """
A[:,:,:2] *= A[:,:,:2]
"""
#~ np.uint8 : 1.23270964172
#~ np.uint16 : 1.3260807837
#~ np.uint32 : 1.32571002402
#~ np.uint64 : 1.76836543305
#~ np.float16 : 2.83364821535
#~ np.float32 : 1.31282323872
#~ np.float64 : 1.44151875479

stmt5 = """
A[:,:,:2] = A[:,:,:2] * A[:,:,:2]
"""
#~ np.uint8 : 1.38166223494
#~ np.uint16 : 1.49569114821
#~ np.uint32 : 1.53105315419
#~ np.uint64 : 2.03457943366
#~ np.float16 : 3.01117795524
#~ np.float32 : 1.51807271679
#~ np.float64 : 1.7164808877

stmt6 = """
A *= 4
A /= 4
"""
#~ np.uint8 : 0.698176392658
#~ np.uint16 : 0.709560468038
#~ np.uint32 : 0.701653066443
#~ np.uint64 : 1.64199069295
#~ np.float16 : 4.86752675499
#~ np.float32 : 0.421001675475
#~ np.float64 : 0.433056710408

stmt7 = """
np.left_shift(A, 2, A)
np.right_shift(A, 2, A)
"""
#~ np.uint8 : 0.381521115341
#~ np.uint16 : 0.383545967785
#~ np.uint32 : 0.386147272415
#~ np.uint64 : 0.665969478824


for stmt in [stmt1, stmt2, stmt3, stmt4, stmt5, stmt6, stmt7]:
    print stmt
    for d in datatypes:
        s = setup.replace("datatype", d)
        T = timeit.Timer(stmt=stmt, setup=s)
        print d,":", min(T.repeat(number=30))
    print
print

float16がとても遅いのはなぜですか?float32が非常に高速なのはなぜですか?多くの場合、整数演算よりも高速です。

関連するパフォーマンスのヒントがあれば、聞いていただければ幸いです。

これは、Windows864ビットのPython2.6.632ビットです。Numpy 1.6、Numpy1.7の数値は同様です。MKL最適化バージョンを今すぐテストします:http ://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy

編集:MKLバージョンは、一部の浮動小数点の場合はわずかに高速ですが、整数演算の場合はかなり遅くなることがあります。

stmt2 = """
A *= 255
A /= 255
A -= 1
A += 1
"""
#np1.6
#~ np.uint8 : 0.959514497259
#~ np.uint16 : 0.988570167659
#~ np.uint32 : 0.963571471946
#~ np.uint64 : 2.07768933333
#~ np.float16 : 9.40085450056
#~ np.float32 : 0.882363984225
#~ np.float64 : 0.910147440048

# np1.7
#~ np.uint8 : 0.979
#~ np.uint16 : 1.010
#~ np.uint32 : 0.972
#~ np.uint64 : 2.081
#~ np.float16 : 9.362
#~ np.float32 : 0.882
#~ np.float64 : 0.918

# np1.7 mkl
#~ np.uint8 : 1.782
#~ np.uint16 : 1.145
#~ np.uint32 : 1.265
#~ np.uint64 : 2.088
#~ np.float16 : 9.029
#~ np.float32 : 0.800
#~ np.float64 : 0.866
4

2 に答える 2

25

半精度演算 (float16) は、基になる C 言語 (および適切なプロセッサ命令) に対応する型がないため、numpy で「エミュレート」する必要があると思います。一方、単精度 (float32) および倍精度 (float64) 演算は、ネイティブ データ型を使用して非常に効率的に実行できます。

単精度演算の良好なパフォーマンスについて: 最新のプロセッサには、ベクトル化された浮動小数点演算 (AVX など) 用の効率的なユニットがあり、優れたマルチメディア パフォーマンスにも必要です。

于 2013-03-11T14:33:43.810 に答える
11

16 ビット浮動小数点数は、ほとんどの一般的な CPU では直接サポートされていません (ただし、グラフィック カード ベンダーは明らかにこのデータ型に関与しているため、GPU が最終的にサポートすることを期待しています)。比較的遅い方法で、それらがエミュレートされることを期待しています。Google によると、float16 はかつてハードウェアに依存していたため、サポートされていないハードウェアでエミュレートしたいと考えている人もいましたが、それが実際に起こったかどうかについては何もわかりませんでした。

一方、32 ビット float はネイティブでサポートされているだけでなく、SIMD 命令セット拡張を使用して多くの操作をベクトル化することもできます。これにより、ベンチマークする種類の操作のオーバーヘッドが大幅に削減されます。例外はデータのシャッフルですが、その場合、float32 は int32 と同等であり、どちらも同じ SIMD 命令を使用して、より大きなメモリ ブロックをロードおよび格納できます。

整数演算用の SIMD 命令もありますが、あまり一般的ではなく (たとえば、SEE は浮動小数点バージョンより後のバージョンで導入されました)、洗練されていないことがよくあります。私の推測では、(あなたのビルドの) NumPy には、あなたにとって遅い操作の SIMD 実装がありません。または、整数演算が最適化されていない可能性があります。浮動小数点数は、パフォーマンスが重要なベクトル化が容易な多くのアプリケーション (画像/メディア/ビデオのエンコードとデコードなど) で使用されるため、より最適化されている可能性があります。

于 2013-03-11T14:38:39.037 に答える