我一直在绞尽脑汁想要完成这项任务一周,我希望有人能带领我走向正确的道路.让我从教师的指示开始:
您的作业与我们的第一个实验作业相反,即优化素数计划.你在这个任务中的目的是使程序失望,即让它运行得更慢.这两个都是CPU密集型程序.他们需要几秒钟才能在我们的实验室电脑上运行.您可能无法更改算法.
要取消优化程序,请使用您对英特尔i7管道如何运行的了解.想象一下重新排序指令路径以引入WAR,RAW和其他危险的方法.想一想最小化缓存有效性的方法.恶魔无能.
该作业选择了Whetstone或Monte-Carlo程序.缓存有效性评论大多只适用于Whetstone,但我选择了Monte-Carlo模拟程序:
// Un-modified baseline for pessimization, as given in the assignment
#include <algorithm> // Needed for the "max" function
#include <cmath>
#include <iostream>
// A simple implementation of the Box-Muller algorithm, used to generate
// gaussian random numbers - necessary for the Monte Carlo method below
// Note that C++11 actually provides std::normal_distribution<> in
// the <random> library, which can be used instead of this function
double gaussian_box_muller() {
double x = 0.0;
double y = 0.0; …Run Code Online (Sandbox Code Playgroud) 我需要一个这样的函数:
// return true iff 'n' is a power of 2, e.g.
// is_power_of_2(16) => true is_power_of_2(3) => false
bool is_power_of_2(int n);
Run Code Online (Sandbox Code Playgroud)
任何人都可以建议我怎么写这个?你能告诉我一个可以找到这种算法的好网站吗?
我改编了我在 SO 上找到的 SSE2 函数,并将其包含在我的程序中。该函数使用 SSE2 内在函数来计算向量中每个 8 x 16 位整数的前导零计数。当我编译这个程序时,它没有产生任何警告,并在我经常用于开发的旧笔记本电脑上运行它,它崩溃并显示消息“非法指令(核心转储)”。在检查程序集时,我注意到我的函数似乎具有 AVX1“VEX”编码的 SSE2 指令,如下所示。
.globl _mm_lzcnt_epi32
.type _mm_lzcnt_epi32, @function
_mm_lzcnt_epi32:
.LFB5318:
.cfi_startproc
endbr64
vmovdqa64 %xmm0, %xmm1
vpsrld $8, %xmm0, %xmm0
vpandn %xmm1, %xmm0, %xmm0
vmovdqa64 .LC0(%rip), %xmm1
vcvtdq2ps %xmm0, %xmm0
vpsrld $23, %xmm0, %xmm0
vpsubusw %xmm0, %xmm1, %xmm0
vpminsw .LC1(%rip), %xmm0, %xmm0
ret
.cfi_endproc
Run Code Online (Sandbox Code Playgroud)
如果我将头文件 immintrin.h 更改为 emmintrin.h,它会将我的代码正确编译为 SSE2 指令
.globl _mm_lzcnt_epi32
.type _mm_lzcnt_epi32, @function
_mm_lzcnt_epi32:
.LFB567:
.cfi_startproc
endbr64
movdqa %xmm0, %xmm1
psrld $8, %xmm0
pandn %xmm1, %xmm0
cvtdq2ps %xmm0, …Run Code Online (Sandbox Code Playgroud) 我在看 HJ Lu 的PATCH: Update x86 rdrand internals。我不知道是否应该使用_rdrand_u64, _rdrand64_step,或者是否还有其他功能。似乎没有为他们编写的测试用例。
似乎也缺少手册页(来自 Ubuntu 14、GCC 4.8.4):
$ man -k rdrand
rdrand: nothing appropriate.
Run Code Online (Sandbox Code Playgroud)
如何使用RDRAND内在函数生成一个 32 字节的块?
一个相关的问题是RDRAND 和 RDSEED 内在函数 GCC 和 Intel C++。但它没有告诉我如何使用它们,或者如何生成一个块。
我正在尝试测试一些英特尔内部函数,看看它们是如何工作的.所以,我创建了一个函数来为我做这个,这是代码:
void test_intel_256()
{
__m256 res,vec1,vec2;
__M256_MM_SET_PS(vec1, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0);
__M256_MM_SET_PS(vec1, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0);
__M256_MM_ADD_PS(res,vec1,vec2);
if (res[0] ==9 && res[1] ==9 && res[2] ==9 && res[3] ==9
&& res[4] ==9 && res[5] ==9 && res[6] ==9 && res[7] ==9 )
printf("Addition : OK!\n");
else
printf("Addition : FAILED!\n");
}
Run Code Online (Sandbox Code Playgroud)
但后来我收到了这些错误:
error: unknown type name ‘__m256’
error: subscripted value is neither array nor pointer nor vector
error: subscripted value is neither array …Run Code Online (Sandbox Code Playgroud) 我在 corei7 上的 ubuntu 上运行 gcc 版本 4.8.2。
从谷歌搜索中找到了有关 AVX 内在函数的信息,但我不确定这组内在函数是否可以用于 Linux 设备驱动程序并对其进行编译。
如果可以,这里的任何人都可以告诉我什么是 makefile 的正确设置以及在 c 源中包含哪些头文件以使用 gcc 编译这个 avx?
谢谢。
我一直在阅读有关哪个头文件更适合访问英特尔内在函数的意见:x86intrin.h或immintrin.h。
两者似乎都达到了相同的结果,但我确信在代码可移植性方面一定存在一些细微的差异。也许其中一个比另一个更常见或更完整?
我找不到对其中任何一个的解释。如果有人知道为什么有两个文件,以及它们有什么区别,这将是一个受欢迎的答案。
说到可移植性,对于较旧的编译器(例如gcc< v4.4.0),事情当然会变得更加复杂,而且两者都不可用。必须考虑包含另一个内在标头(可能emmintrin.h用于 SSE 支持)。
gcc ×4
intel ×4
intrinsics ×4
c ×3
c++ ×3
avx ×2
algorithm ×1
assembly ×1
header ×1
header-files ×1
linux-kernel ×1
optimization ×1
rdrand ×1
x86 ×1