不,那没有任何意义。这就像在运行时尝试根据某个变量的值选择 uint32_t 还是 uint64_t。
手动向量化不通过将整个数组视为一个巨大的 SIMD 向量来工作,它通过告诉编译器确切地告诉编译器如何使用固定大小的短向量来工作。如果自动矢量化不适用于普通数组,这将无济于事。
如果您不想手动执行循环,要让 GCC “更努力地”自动矢量化循环,#pragma omp SIMD 和 gcc -fopenmp 可以在 -O2 自动矢量化。或者使用-O3 进行编译会将每个循环都视为自动矢量化的候选对象。 (还有关于单个结构的东西;不过,clang 通常比 gcc 更擅长在非循环代码中找到 SIMD 用例。clang 有时可能过于激进,并且花费更多时间将数据混洗在一起,而不是单独进行标量工作.)
但请注意,GCC 和 clang 的自动矢量化只有在循环行程计数可以在第一次迭代之前计算时才能工作。它可以是运行时变量计数,但可能会根据数据随时触发的if()break; 退出条件会破坏它们。所以例如他们无法自动矢量化使用 while(*p++ != 0){...} 的幼稚循环 strlen 或 strchr 实现。 ICC 可以做到这一点。
此外,如果您需要任何类型的改组,您通常需要自己使用 GNU C 本机向量或特定目标的内在函数(例如 x86 的 SSE/AVX、ARM 的 NEON/AdvSIMD、Power 的 AltiVec 等) .
Cray 机器显然有 SIMD,它通过给硬件一个指针 + 长度并让它在它想要的任何块中“循环”来工作(可能就像现代 x86 rep movsd 实际上可以在其微码中使用更大的块一样)。但现代 CPU 具有固定宽度的短向量 SIMD 指令,例如可以执行 16 或 32 个字节。
(ARM SVE 介于两者之间,它允许代码向前兼容以利用未来硬件上更宽的向量,而不是完全以向量宽度烘焙。不过,它仍然是您无法控制的固定大小。你仍然必须循环使用它,并通过硬件的向量宽度增加你的指针.它有掩蔽的东西来忽略你想要处理的结束之后的元素,所以你可以将它用于任意短的数组,我认为,并且数组的剩余端。但是对于任意长的数组,您仍然需要循环。此外,很少有 CPU 支持 SVE。顺便说一句,SVE 与Agner Fog's ForwardCom blue-sky paper architecture 中的 SIMD 类似的概念,其目的也是让代码利用未来更广泛的硬件,而无需重新编译或重做手动矢量化。)
当您针对具有固定宽度 SIMD 向量的机器(例如选择 16 或 32)时,您希望从 运行时 可变大小的“向量”中获得什么样的 asm 代码生成字节,选择作为指令编码的一部分?