- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想将 signed char vector 转换为 unsigned char vector 。我想保留每种类型的值范围。
我的意思是,当 unsigned char 元素的值范围在 0 - 255 之间时,signed char 的值范围是 -128 和 +127。
没有内在函数,我几乎可以这样做:
#include <iostream>
int main(int argc,char* argv[])
{
typedef signed char schar;
typedef unsigned char uchar;
schar a[]={-1,-2,-3,4,5,6,-7,-8,9,10,-11,12,13,14,15,16,17,-128,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
uchar b[32] = {0};
for(int i=0;i<32;i++)
b[i] = 0xFF & ~(0x7F ^ a[i]);
return 0;
}
所以我使用 AVX2 编写了以下程序:
#include <immintrin.h>
#include <iostream>
int main(int argc,char* argv[])
{
schar a[]={-1,-2,-3,4,5,6,-7,-8,9,10,-11,12,13,14,15,16,17,-128,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
uchar b[32] = {0};
__m256i _a = _mm256_stream_load_si256(reinterpret_cast<const __m256i*>(a));
__m256i _b;
__m256i _cst1 = _mm256_set1_epi8(0x7F);
__m256i _cst2 = _mm256_set1_epi8(0xFF);
_a = _mm256_xor_si256(_a,_cst1);
_a = _mm256_andnot_si256(_cst2,_a);
// The way I do the convertion is inspired by an algorithm from OpenCV.
// Convertion from epi8 -> epi16
_b = _mm256_srai_epi16(_mm256_unpacklo_epi8(_mm256_setzero_si256(),_a),8);
_a = _mm256_srai_epi16(_mm256_unpackhi_epi8(_mm256_setzero_si256(),_a),8);
// convert from epi16 -> epu8.
_b = _mm256_packus_epi16(_b,_a);
_mm256_stream_si256(reinterpret_cast<__m256i*>(b),_b);
return 0;
}
当我显示变量 b 时,它完全是空的。我还检查以下情况:
#include <immintrin.h>
#include <iostream>
int main(int argc,char* argv[])
{
schar a[]={-1,-2,-3,4,5,6,-7,-8,9,10,-11,12,13,14,15,16,17,-128,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
uchar b[32] = {0};
__m256i _a = _mm256_stream_load_si256(reinterpret_cast<const __m256i*>(a));
__m256i _b;
__m256i _cst1 = _mm256_set1_epi8(0x7F);
__m256i _cst2 = _mm256_set1_epi8(0xFF);
// The way I do the convertion is inspired by an algorithm from OpenCV.
// Convertion from epi8 -> epi16
_b = _mm256_srai_epi16(_mm256_unpacklo_epi8(_mm256_setzero_si256(),_a),8);
_a = _mm256_srai_epi16(_mm256_unpackhi_epi8(_mm256_setzero_si256(),_a),8);
// convert from epi16 -> epu8.
_b = _mm256_packus_epi16(_b,_a);
_b = _mm256_xor_si256(_b,_cst1);
_b = _mm256_andnot_si256(_cst2,_b);
_mm256_stream_si256(reinterpret_cast<__m256i*>(b),_b);
return 0;
}
和:
#include <immintrin.h>
#include <iostream>
int main(int argc,char* argv[])
{
schar a[]={-1,-2,-3,4,5,6,-7,-8,9,10,-11,12,13,14,15,16,17,-128,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
uchar b[32] = {0};
__m256i _a = _mm256_stream_load_si256(reinterpret_cast<const __m256i*>(a));
__m256i _b;
__m256i _cst1 = _mm256_set1_epi8(0x7F);
__m256i _cst2 = _mm256_set1_epi8(0xFF);
// The way I do the convertion is inspired by an algorithm from OpenCV.
// Convertion from epi8 -> epi16
_b = _mm256_srai_epi16(_mm256_unpacklo_epi8(_mm256_setzero_si256(),_a),8);
_a = _mm256_srai_epi16(_mm256_unpackhi_epi8(_mm256_setzero_si256(),_a),8);
_a = _mm256_xor_si256(_a,_cst1);
_a = _mm256_andnot_si256(_cst2,_a);
_b = _mm256_xor_si256(_b,_cst1);
_b = _mm256_andnot_si256(_cst2,_b);
_b = _mm256_packus_epi16(_b,_a);
_mm256_stream_si256(reinterpret_cast<__m256i*>(b[0]),_b);
return 0;
}
我的调查显示部分问题与 and_not 操作有关。但我不明白为什么。
变量 b 应包含以下序列:[127、126、125、132、133、134、121、120、137、138、117、140、141、141、142、142、143、144、145、147、147、148、148、149、149、150、151、151、152、152、153 , 154, 155, 156, 157, 158, 159, 160]。
在此先感谢您的帮助。
最佳答案
您只是在谈论将 128
添加到每个字节,对吗?这会将范围从 [-128..127]
转移到 [0..255]
。当您只能使用 8 位操作数时,加 128 的技巧是减去 -128。
但是,当结果被截断为 8 位时,添加 0x80
也同样有效。 (因为补码)。添加很好,因为操作数的顺序无关紧要,因此编译器可以使用加载和添加指令(将内存操作数折叠到加载中)。
加法/减法 -128,进位/借位由元素边界停止,等同于 xor
(也称为无进位加法)。使用 pxor
可能是通过 Broadwell 在 Intel Core2 上的一个小优势,因为 Intel 一定认为在端口 0 上为 Skylake 添加 paddb/w/d/q
硬件是值得的(每 0.333c 吞吐量给他们一个,如 pxor
)。 (感谢@harold 指出这一点)。两条指令都只需要 SSE2。
XOR 也可能对 SWAR 有用未对齐清理,或用于没有字节大小加/减操作的 SIMD 架构。
你不应该使用 _a
作为你的变量名。 _
名称是保留的。我倾向于使用 veca
或 va
之类的名称,最好是对临时对象更具描述性的名称。 (如 a_unpacked
)。
__m256i signed_bytes = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(a));
__m256i unsigned_bytes = _mm256_add_epi8(signed_bytes, _mm256_set1_epi8(-128));
是的,就是这么简单,您不需要二进制补码。一方面,您的方式需要两个单独的 32B 掩码,这会增加您的缓存占用空间。 (但请参阅 What are the best instruction sequences to generate vector constants on the fly? 您(或编译器)可以使用 3 条指令生成 -128
字节的 vector ,或者从 4B 常量进行广播加载。)
仅将 _mm256_stream_load_si256
用于 I/O(例如从视频 RAM 读取)。不要用它来读取“正常”(回写)内存;它不做你认为它做的事。 (不过,我认为它没有任何特别的缺点。它就像正常的 vmovdqa
加载一样工作)。我在 another answer I wrote recently 中放置了一些相关链接.
流式存储 对普通(回写)内存区域很有用。但是,仅您不打算很快再次阅读该内存时,它们是个好主意。如果是这种情况,您可能应该在读取此数据的代码中即时执行从有符号到无符号的转换,因为它非常便宜。只需将您的数据保留为一种格式或另一种格式,然后在需要它的代码中即时转换为另一种格式。与在某些循环中保存一条指令相比,在缓存中只需要它的一个拷贝是一个巨大的胜利。
还可以在谷歌上搜索“缓存阻塞”(又名循环平铺)并阅读有关优化代码以在小块中工作以增加计算密度的信息。 (尽可能多地处理缓存中的数据。)
关于c++ - 使用 AVX2 和范围保存的按位类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35191398/
我不能解决这个问题。和标题说的差不多…… 如果其他两个范围/列中有“否”,我如何获得范围或列的平均值? 换句话说,我想计算 A 列的平均值,并且我有两列询问是/否问题(B 列和 C 列)。我只希望 B
我知道 python 2to3 将所有 xrange 更改为 range 我没有发现任何问题。我的问题是关于它如何将 range(...) 更改为 list(range(...)) :它是愚蠢的,只是
我有一个 Primefaces JSF 项目,并且我的 Bean 注释有以下内容: @Named("reportTabBean") @SessionScoped public class Report
在 rails3 中,我在模型中制作了相同的范围。例如 class Common ?" , at) } end 我想将公共(public)范围拆分为 lib 中的模块。所以我试试这个。 module
我需要在另一个 View 范围 bean 中使用保存在 View 范围 bean 中的一些数据。 @ManagedBean @ViewScoped public class Attivita impl
为什么下面的代码输出4?谁能给我推荐一篇好文章来深入学习 javascript 范围。 这段代码返回4,但我不明白为什么? (function f(){ return f(); functio
我有一个与此结构类似的脚本 $(function(){ var someVariable; function doSomething(){ //here } $('#som
我刚刚开始学习 Jquery,但这些示例对我帮助不大...... 现在,以下代码发生的情况是,我有 4 个表单,我使用每个表单的链接在它们之间进行切换。但我不知道如何在第一个函数中获取变量“postO
为什么当我这样做时: function Dog(){ this.firstName = 'scrappy'; } Dog.firstName 未定义? 但是我可以这样做: Dog.firstNa
我想打印文本文件 text.txt 的选定部分,其中包含: tickme 1.1(no.3) lesson1-bases lesson2-advancedfurther para:using the
我正在编写一些 JavaScript 代码。我对这个关键字有点困惑。如何在 dataReceivedHandler 函数中访问 logger 变量? MyClass: { logger: nu
我有这个代码: Public Sub test() Dim Tgt As Range Set Tgt = Range("A1") End Sub 我想更改当前为“A1”的 Tgt 的引
我正忙于此工作,以为我会把它放在我们那里。 该数字必须是最多3个单位和最多5个小数位的数字,等等。 有效的 999.99999 99.9 9 0.99999 0 无效的 -0.1 999.123456
覆盖代码时: @Override public void open(ExecutionContext executionContext) { super.open(executio
我想使用 preg_match 来匹配数字 1 - 21。我如何使用 preg_match 来做到这一点?如果数字大于 21,我不想匹配任何东西。 example preg_match('([0-9]
根据docs range函数有四种形式: (range) 0 - 无穷大 (range end) 0 - 结束 (range start end)开始 - 结束 (range start end st
我知道有一个UISlider,但是有人已经制作了RangeSlider(用两个拇指吗?)或者知道如何扩展 uislider? 最佳答案 我认为你不能直接扩展 UISlider,你可能需要扩展 UICo
我正在尝试将范围转换为列表。 nums = [] for x in range (9000, 9004): nums.append(x) print nums 输出 [9000] [9
请注意:此问题是由于在运行我的修饰方法时使用了GraphQL解析器。这意味着this的范围为undefined。但是,该问题的基础知识对于装饰者遇到问题的任何人都是有用的。 这是我想使用的基本装饰器(
我正在尝试创建一个工具来从网页上抓取信息(是的,我有权限)。 到目前为止,我一直在使用 Node.js 结合 requests 和 Cheerio 来拉取页面,然后根据 CSS 选择器查找信息。我已经
我是一名优秀的程序员,十分优秀!