numpy 泡沫型现浇

wljmcqd8  于 2023-01-26  发布在  其他
关注(0)|答案(1)|浏览(81)

我有一个浮点数dtype=np.float32的numpy数组phase,我把它转换成整数outdtype=np.uint8,因为速度是个问题,所以应该就地转换。
我使用以前学员的代码,但代码无法正常工作

phase = np.arange(0, 4, dtype=np.float32).reshape(2, 2)

out = np.empty((2, 2), dtype=np.uint8)

# Prepare the 2pi -> integer conversion factor and convert.
factor = -(256 / 2 / np.pi)
phase *= factor

print("array phase with dtype float \n ", phase)

# There is some randomness involved in casting positive floats to integers.
# Avoid this by going all negative.
maximum = np.amax(phase)
if maximum >= 0:
    toshift = 256 * 2 * np.ceil(maximum / 256)
    phase -= toshift

# Copy and cast the data to the output
np.copyto(out, phase, casting="unsafe")
print("phase array dtype unsigned integer", out)

# This part (along with the choice of type), implements modulo much faster than np.mod().
bw = int(256 - 1)
np.bitwise_and(out, bw, out=out)
print("array module bit depth \n", out)

输出为

array phase with dtype float 
  [[  -0.      -162.97466]
 [-325.9493  -488.92395]]
phase array dtype unsigned integer [[  0  94]
 [187  24]]
array module bit depth 
 [[  0  94]
 [187  24]]

执行此程序会产生我无法理解的结果:
1.例如,为什么-162Map到94?
1.我知道标记casting=unsafe,但它是就地转换所必需的。
1.我也意识到300 > 256np.uint8数据类型太小了,我想我应该把它增加到np.uint16
1.为什么在将正浮点数强制转换为整数时会涉及一些随机性?
我也试过np.astype(np.uint8),但结果同样令人失望。

lc8prwob

lc8prwob1#

由于速度是一个问题,这应该就地进行。
就地操作并不总是需要更快。这取决于目标平台和Numpy的编译方式(需要考虑很多底层影响)。尽管它们通常不会更慢。在某些情况下重用缓冲区就足够了(以避免页面错误)。您是否 * 剖析 * 了您的代码并发现这是一个 * 瓶颈 *?
例如,为什么-162Map到94?
这是因为目标类型的范围(包括0..255)不支持数字-162,实际上也不支持任何负数,因为它是一个8位的无符号整数。256-162=94。也就是说,AFAIK,这样做会导致一个 * 未定义的行为 。结果从一个平台到另一个平台可能会改变(实际上是基于过去的Numpy问题)。因此,我强烈建议使用一个更大的类型或更改您的代码,以便值适合目标输出类型范围。
我知道标志铸造=不安全,但它需要就地转换。
casting=unsafe非常明确,它的基本意思是:"
我确切地知道我在做什么,并接受风险和后果 *"。使用它的风险自担;)。
我也注意到300〉256,因此np.uint8数据类型太小了,我想我应该把它增加到np.uint16?
因为数字是负数,你应该用np.int16来代替。除了这个,是的,这是个好主意。
为什么在将正浮点数强制转换为整数时会涉及一些随机性?
这并不是真正的随机,这种操作是确定性的,但结果取决于目标平台和输入的数字(也可能取决于处理器针对特定目标平台的低级状态),实际上,只要输入的数字在目标范围内,并且没有NaN、+Inf、-Inf值等特殊数字,就可以了。
我也尝试过np.astype(np.uint8),但结果同样令人失望。
这是正常的。问题是相同的,在两种情况下都调用了相同的转换函数。
注意,除了np.bitwise_and(out, bw, out=out)之外,你所做的操作实际上并不是一个就地操作。也就是说,它对np.uint8类型是无用的,因为范围被限制在255以内。
实现模运算比np.mod()快得多
这对于正数是正确的,但是对于负数不是。对于负数,这取决于目标平台上的整数的底层表示。这对于使用C1表示的处理器不起作用。也就是说,现在所有的主流处理器都使用C2表示。

相关问题