Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【Hackathon 5th No.34】 为 Paddle 新增 bitwise_right_shift / bitwise_right_shift_ / bitwise_left_shift / bitwise_left_shift_ API (update RFC) #788

Merged
merged 5 commits into from
Jan 5, 2024

Conversation

Copy link

paddle-bot bot commented Dec 18, 2023

你的PR提交成功,感谢你对开源项目的贡献!
请检查PR提交格式和内容是否完备,具体请参考示例模版
Your PR has been submitted. Thanks for your contribution!
Please check its format and content. For this, you can refer to Template and Demo.

@cocoshe
Copy link
Contributor Author

cocoshe commented Dec 20, 2023

@xuxinyi389 补充了更详细的描述,对比了竞品的具体实现,pr中bitwise_functors.h的实现和这一部分相对应,辛苦review~

具体行为定义:(`n_bits`表示数据类型存储位数,例如int8的`n_bits`为8,uint16的`n_bits`为16;当`y`小于0时为“未定义行为”,等效于位移超过最大位数溢出)

+ 算术位移

  + 算术左移:当`y`小于0,或者`y`大于等于`n_bits`时候溢出,返回0;否则正常位移;
  + 算术右移:
    + 有符号数时:当`y`小于0,或者`y`大于等于`n_bits`时候溢出,返回符号位(`a>>(n_bits-1)&1`);否则正常位移;
    + 无符号数时:当`y`小于0,或者`y`大于等于`n_bits`时候溢出,返回0;否则正常位移;

+ 逻辑位移

  + 逻辑左移:当`y`小于0,或者`y`大于等于`n_bits`时候溢出,返回0;否则正常位移;

  + 逻辑右移:

    + 有符号数时:当`y`小于0,或者`y`大于等于`n_bits`时候溢出,返回0;否则特殊位移:

      ```cpp
      template <typename T>
      HOSTDEVICE T logic_shift_func(const T a, const T b) {
        if (b < static_cast<T>(0) || b >= static_cast<T>(sizeof(T) * 8))
          return static_cast<T>(0);
        T t = static_cast<T>(sizeof(T) * 8 - 1);
        T mask = (((a >> t) << t) >> b) << 1;
        return (a >> b) ^ mask;
      }
      ```

      在`T mask = (((a >> t) << t) >> b) << 1;`中,先`(a >> t)`取符号位,然后`<< t`回到原位,再右移`b`后左移一位,最后与`a>>b`的结果做亦或,下面举两个例子:

      ```
      example1:
      a = 1001,1010  b = 3, 有t=7
      ((a>>t)<<t) = 1000,0000
      mask=(((a>>t)<<t)>>b)<<1 = 1110,0000
      a>>b = 1111,0011
      所以 (a>>b) ^ mask = 0001,0011
      
      example2:
      a = 0001,1010 b = 3, 有t=7
      ((a>>t)<<t) = 0000,0000
      mask=(((a>>t)<<t)>>b)<<1 = 0000,0000
      a>>b = 0000,0011
      所以 (a>>b) ^ mask = 0000,0011
      ```

    + 无符号数时:当`y`小于0,或者`y`大于等于`n_bits`时候溢出,返回0;否则正常位移;

  以上行为中,算术位移与numpy、pytorch的实现对齐;由于numpy和pytorch不支持逻辑位移,所以逻辑位移参考jax的实现思路,用numpy来进行间接实现和验证。


具体行为定义:(`n_bits`表示数据类型存储位数,例如int8的`n_bits`为8,uint16的`n_bits`为16;当`y`小于0时为“未定义行为”,等效于位移超过最大位数溢出)

+ 算术位移

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注意到一种情形,比如x为有符号数,比如x=-45(int8),无论是算术移位还是逻辑移位,其左移2位为76,左移3位为-104。这种有符号数左移出现时正时负的情形,可能会让人迷惑,RFC中还可以详细描述下不同情形下,对于有符号数x的符号位的处理逻辑,相应的例子和描述也可以更新到API文档中。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注意到一种情形,比如x为有符号数,比如x=-45(int8),无论是算术移位还是逻辑移位,其左移2位为76,左移3位为-104。这种有符号数左移出现时正时负的情形,可能会让人迷惑,RFC中还可以详细描述下不同情形下,对于有符号数x的符号位的处理逻辑,相应的例子和描述也可以更新到API文档中。

嗯嗯好,这种属于溢出,位移溢出的结果都是不可控无意义的,我说明一下~

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

补充下竞品对于未定义操作的的实际处理方式,看是否和当前现有设计方案是一致的

+ 有符号数时,例如`int8 x=-100`,补码为`1001,1100`,最高位为符号位,仅需要右移7位,所有的`int8`就都会变成`1111,1111`,即`-1`;
+ 无符号数时候,例如`uint8 x=200`,存储为`1100,1000`,八位均表示数值大小,需要右移8位才可以将所有的`uint8`变为`0000,0000`,即`0`;
+ 当`b`位负数这一未定义行为时,同样等效于右移无穷位,与移动`max_shift`等效,有符号数变为`-1`,无符号数变为`0`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

错别字,“位“应该为”为“。对于未定义的行为怎么处理,应该列出竞品实际是如何处理的,处理方式是否一致,这些都是要说清楚的。

@cocoshe
Copy link
Contributor Author

cocoshe commented Jan 2, 2024

@xuxinyi389 应该比较详细了,哪里有疏漏的话我再补充一些,辛苦review~

@@ -145,7 +145,9 @@ void rshift_kernel_cuda(TensorIteratorBase& iter) {
+ 算术右移时,`max_shift`需要考虑最大的移动距离,有符号数最高位为符号位,故表示数值的位数实际上会少一位。
+ 有符号数时,例如`int8 x=-100`,补码为`1001,1100`,最高位为符号位,仅需要右移7位,所有的`int8`就都会变成`1111,1111`,即`-1`;
+ 无符号数时候,例如`uint8 x=200`,存储为`1100,1000`,八位均表示数值大小,需要右移8位才可以将所有的`uint8`变为`0000,0000`,即`0`;
+ 当`b`位负数这一未定义行为时,同样等效于右移无穷位,与移动`max_shift`等效,有符号数变为`-1`,无符号数变为`0`
+ 当`b`位负数这一未定义行为时,同样等效于右移无穷位,与移动`max_shift`等效(从代码中可以看到,`b<0`和`b>=max_shift`是在同一个`if`判断中),只要满足两个条件中任意一个,则使得有符号数变为`-1`,无符号数变为`0`。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“当‘b’位负数这一未定义行为时“,有个错别字“位“应该为”为“

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“当‘b’位负数这一未定义行为时“,有个错别字“位“应该为”为“

sry,更正了~

@xuxinyi389
Copy link

LGTM

@luotao1 luotao1 merged commit b109db8 into PaddlePaddle:master Jan 5, 2024
1 check passed
@cocoshe cocoshe deleted the bitwise_shift_rfc_update branch January 5, 2024 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants