Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gcc向量扩展是否支持可变长度向量?_C_Gcc_Vector_Simd_C99 - Fatal编程技术网

gcc向量扩展是否支持可变长度向量?

gcc向量扩展是否支持可变长度向量?,c,gcc,vector,simd,c99,C,Gcc,Vector,Simd,C99,这似乎不起作用/无法编译 void vec(size_t n) { typedef char v4si __attribute__((vector_size(n))); v4si t={1}; } 有没有合适的方法来声明它或者它不受支持?没有,那没有意义。这就像在运行时根据某个变量的值选择uint32\u t和uint64\u t一样 手动矢量化不能将整个数组视为一个巨大的SIMD矢量,它的工作原理是准确地告诉编译器如何使用固定大小的短矢量。如果自动矢量化在普通数组中不起作用,

这似乎不起作用/无法编译

void vec(size_t n) {
    typedef char v4si __attribute__((vector_size(n)));
    v4si t={1};
}

有没有合适的方法来声明它或者它不受支持?

没有,那没有意义。这就像在运行时根据某个变量的值选择uint32\u t和uint64\u t一样

手动矢量化不能将整个数组视为一个巨大的SIMD矢量,它的工作原理是准确地告诉编译器如何使用固定大小的短矢量。如果自动矢量化在普通数组中不起作用,这将无济于事

为了让GCC更努力地自动矢量化循环(如果您不想手动执行),这里有一个pragma omp SIMD和GCC-fopenmp,它可以在-O2处自动矢量化。或者用-O3编译将考虑每个循环作为自动矢量化的候选。也可以在单个结构上填充内容;不过,与gcc相比,clang通常更擅长在非循环代码中查找SIMD用例。clang有时可能过于激进,将数据混合在一起的时间比单独执行标量工作花费的时间要多

但请注意,GCC和clang的自动矢量化只能在第一次迭代之前计算循环行程计数时才起作用。它可以是运行时变量计数,但不能是ifbreak;根据数据随时可能触发的退出条件将使其失效。例如,他们不能自动矢量化使用while*p++!=0{...}. 国际刑事法院可以做到这一点

此外,如果您需要任何类型的洗牌,您通常需要自己使用GNU C本机向量或特定于目标的内部函数,如用于x86的SSE/AVX、用于ARM的NEON/AdvSIMD、用于Power的AltiVec等

Cray machines显然有一个SIMD,它通过给硬件一个指针+长度,并让它在它想要的块中循环,就像现代x86 rep movsd实际上可以在其微码中使用更大的块一样。但现代CPU有固定宽度的短向量SIMD指令,例如,它可以精确地执行16或32字节

ARM SVE在某种程度上介于两者之间,允许代码的前向兼容性利用未来硬件上更宽的向量,而不是在向量宽度内完全烘焙。但它仍然是一个你无法控制的固定尺寸。您仍然必须使用它进行循环,并将指针增加硬件的向量宽度。它有掩蔽功能,可以忽略要处理的结束后的元素,因此可以将其用于任意短的数组,我认为,也可以用于数组的剩余端。但是对于任意长的数组,仍然需要循环。此外,很少有CPU支持SVE。顺便说一句,SVE与blue sky paper architecture中的SIMD概念相似,它还旨在让代码利用未来更广泛的硬件,而无需重新编译或重新进行手动矢量化


当针对具有固定宽度SIMD向量(如16或32字节的选择)的机器时,您希望从运行时可变大小的向量中获得哪种类型的asm代码,而选择作为指令编码的一部分?

因为对于大小,只允许基类型的两倍的正幂,我认为它不被支持。文档中没有提到非常量大小您可以考虑预先定义应用程序中所需的所有类型,并使用一个开关来选择请求的类型。您想在这里实现什么?编写简单的for循环并使用-O3编译是一个选项吗?切换到C++是一种选择吗?您可以将n作为模板参数传递,如果它在编译时已知的话time@chtz问题是gcc倾向于不矢量化简单循环,因此需要明确说明。@BusyBee大小可以是1和10Gb。如果循环没有矢量化,那么您需要检查日志,了解为什么它没有矢量化和修复,尽管有一种特殊情况,即初始化可变长度数组。这里的问题是我需要在一个固定的地址做这件事,据我所知,这个地址只有cilk提供。另外,您的一个说法有点错误,因为arm现在具有可伸缩向量扩展功能,就像克雷机器允许的那样工作。不像霓虹灯,在这种情况下,向量长度可以是任何东西;SVE不是那样工作的。有一个用于确定长度的函数,在递增计数器的同时循环遍历数据。在循环中,根据长度和计数器的剩余元素数生成一个遮罩,因此在最后一次迭代中,机器将遮罩掉所有剩余元素,并且不会触摸它们。请参阅以获取示例。@user2284570:如果memset或wmemset与数组的元素大小匹配,您是否在查找它们?GCC可以内联它们,或者调用一个高效的libc实现。此外,SVE很有趣,值得一提,但SVE不像Cray矢量化或x86 rep stosd。谢谢您提醒我。@PeterCordes我正在为我的自定义分配器重新实现memset。@user2284570:您希望通过调用memset获得什么好处? GCC和clang通常非常擅长编译对memset的调用。手动矢量化最多只能适用于某些微体系结构,这些微体系结构与您正在调试的唯一微体系结构类似,但GCC已经知道适用于不同ISA的不同微体系结构的memset策略。至少在理论上;有时可能会遗漏一些优化,您可以在GCC的bugzilla上报告这些优化。