简体   繁体   English

Numpy 就地式铸造

[英]Numpy in-place type casting

I have a numpy array phase of floats dtype=np.float32 that I convert to integers out , dtype=np.uint8 .我有一个 numpy 数组phase的浮点数dtype=np.float32 ,我将其转换为整数outdtype=np.uint8 Since speed is an issue, this should happen in-place.由于速度是一个问题,这应该就地发生。

I work with code from a previous student and the code doesn't work我使用以前学生的代码,但代码不起作用

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) 

The output is output 是

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]]

Executing this program yields results that I don't understand:执行这个程序会产生我不明白的结果:

  1. Why does eg -162 get mapped to 94?为什么-162 会映射到 94?
  2. I am aware of the flag casting=unsafe but it is required to to in-place conversion.我知道标志casting=unsafe但需要就地转换。
  3. I am also aware that 300 > 256 and hence the np.uint8 data-type is too small.我也知道300 > 256 ,因此np.uint8数据类型太小。 I guess i should increase it to np.uint16 ?我想我应该把它增加到np.uint16吗?
  4. Why is there some randomness involved when casting positive floats to integer?为什么在将正浮点数转换为 integer 时会涉及一些随机性?

I have also tried np.astype(np.uint8) but the results are similarly disappointing.我也试过np.astype(np.uint8)但结果同样令人失望。

Since speed is an issue, this should happen in-place.由于速度是一个问题,这应该就地发生。

In-place operations are not always necessary faster.就地操作并不总是需要更快。 This is dependent of the target platform and the way Numpy is compiled (a lot of low-level effects needs to be considered).这取决于目标平台和 Numpy 的编译方式(需要考虑很多低级影响)。 They are generally not slower though.不过,它们通常并不慢。 Reusing buffers is sufficient in some cases (to avoid page-faults).在某些情况下,重复使用缓冲区就足够了(以避免页面错误)。 Did you profile your code and found this to be a bottleneck ?您是否分析过您的代码并发现这是一个瓶颈

Why does eg -162 get mapped to 94?为什么-162 会映射到 94?

This is because the range of the destination type (0..255 included) does not supports the number -162 nor any negative numbers actually since it is an unsigned integer of 8 bits.这是因为目标类型的范围(包括 0..255)实际上不支持数字 -162 或任何负数,因为它是 8 位的无符号 integer。 As a result, a wraparound happens: 256-162=94 .结果,发生了环绕: 256-162=94 That being said, AFAIK, doing this cause an undefined behaviour .也就是说,据我所知,这样做会导致未定义的行为 The result from one platform to another can change (and actually did so based on past Numpy questions and issues).从一个平台到另一个平台的结果可能会发生变化(实际上是根据过去的 Numpy 问题和问题这样做的)。 Thus, I strongly advise to use a bigger type or to change your code so the values fit in the target output type range.因此,我强烈建议使用更大的类型或更改您的代码,以便值适合目标 output 类型范围。

I am aware of the flag casting=unsafe but it is required to to in-place conversion.我知道标志 casting=unsafe 但需要就地转换。

casting=unsafe is pretty explicit. casting=unsafe非常明确。 It basically means: " I know exactly what I am doing and accept the risks and the consequence ".它基本上意味着:“我清楚地知道我在做什么,并接受风险和后果”。 Use it at your own risk;).需要您自担风险使用它;)。

I am also aware that 300 > 256 and hence the np.uint8 data-type is too small.我也知道 300 > 256,因此 np.uint8 数据类型太小。 I guess i should increase it to np.uint16?我想我应该把它增加到 np.uint16?

Since numbers are negative, you should rather use np.int16 instead.由于数字是负数,您应该改用np.int16 Beside this, yes, this is a good idea.除此之外,是的,这是个好主意。

Why is there some randomness involved when casting positive floats to integer?为什么在将正浮点数转换为 integer 时会涉及一些随机性?

It is not really random.这不是真的随机。 Such operation is deterministic, but the result is dependent of the target platform and the input numbers (and possibly the low-level state of the processor regarding the specific target platform).这种操作是确定性的,但结果取决于目标平台和输入数字(以及可能是处理器的低级 state 与特定目标平台有关)。 In practice, as long as the input numbers fit in the target range and there is no special numbers like NaN, +Inf, -Inf values, it should be fine.实际上,只要输入的数字在目标范围内,并且没有像 NaN、+Inf、-Inf 值这样的特殊数字,就应该没问题。

I have also tried np.astype(np.uint8) but the results are similarly disappointing.我也试过 np.astype(np.uint8) 但结果同样令人失望。

This is normal.这是正常的。 The problem is the same and the same conversion function is called in both cases.问题是相同的,并且在两种情况下都调用了相同的转换 function。


Note the operation you do is not really an in-place operation, except the np.bitwise_and(out, bw, out=out) .请注意,您执行的操作并不是真正的就地操作,除了np.bitwise_and(out, bw, out=out) That being said, it is useless for an np.uint8 type since the range is bounded to 255 anyway.也就是说,它对于np.uint8类型是无用的,因为无论如何范围都限制在 255 以内。

implements modulo much faster than np.mod()实现模比 np.mod() 快得多

This is true for positive number but not for negative numbers.这对正数是正确的,但对负数则不然。 For negative numbers, this is dependent of the underlying representation of integers on the target platform.对于负数,这取决于目标平台上整数的底层表示。 This does not work for processors using the C1 representation.这不适用于使用 C1 表示的处理器。 That being said, all mainstream processors use the C2 representation these days.话虽如此,如今所有主流处理器都使用 C2 表示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM