请不要说这是过早的微观优化.我想了解,尽管我的知识有限,但所描述的SB功能和装配如何工作,并确保我的代码使用这种架构功能.谢谢你的理解.
我几天前开始学习内在函数,所以答案对某些人来说似乎很明显,但我没有可靠的信息来源来解决这个问题.
我需要为Sandy Bridge CPU优化一些代码(这是一项要求).现在我知道它可以在每个周期进行一次AVX乘法和一次AVX加法,并阅读本文:
http://research.colfaxinternational.com/file.axd?file=2012%2F7%2FColfax_CPI.pdf
它展示了如何在C++中完成它.所以,问题是我的代码不会使用英特尔的编译器自动矢量化(这是该任务的另一个要求),所以我决定使用这样的内在函数手动实现它:
__sum1 = _mm256_setzero_pd();
__sum2 = _mm256_setzero_pd();
__sum3 = _mm256_setzero_pd();
sum = 0;
for(kk = k; kk < k + BS && kk < aW; kk+=12)
{
const double *a_addr = &A[i * aW + kk];
const double *b_addr = &newB[jj * aW + kk];
__aa1 = _mm256_load_pd((a_addr));
__bb1 = _mm256_load_pd((b_addr));
__sum1 = _mm256_add_pd(__sum1, _mm256_mul_pd(__aa1, __bb1));
__aa2 = _mm256_load_pd((a_addr + 4));
__bb2 = _mm256_load_pd((b_addr + 4));
__sum2 = _mm256_add_pd(__sum2, _mm256_mul_pd(__aa2, __bb2));
__aa3 = _mm256_load_pd((a_addr …Run Code Online (Sandbox Code Playgroud) 我有一个模板功能,我们称之为"客户端":
template<typename T>
void client(T (*func)(const std::string&), const std::string& s) {}
Run Code Online (Sandbox Code Playgroud)
然后有许多"adaptee"函数都具有相同类型的第一个非默认参数,但以下参数的数量不同并具有默认值:
void adaptee_one(const std::string&, int i = 1, char* c = nullptr) {}
void adaptee_two(const std::string&, float* f = nullptr) {}
Run Code Online (Sandbox Code Playgroud)
以上功能是给定的.现在我想做的是将它们client<>()作为第一个参数传递给上面的函数,我只关心传递第一个参数,const std::string&.所以我做了以下事情:
void bindAdapteeOne(const std::string& s) {
return adaptee_one(s);
}
void bindAdapteeTwo(const std::string& s) {
return adaptee_two(s);
}
Run Code Online (Sandbox Code Playgroud)
然后bindAdapteeX()转到client<>().
我想做的是自动化包装或者有一个(模板化的)包装而不是每个适配器.我觉得可变性可能就是这种情况,但对如何准确应用它们几乎一无所知.
C++ 11很好,如果绝对必要,C++ 14就可以了.
编辑3:图像是指向完整版本的链接.对于文本图片感到抱歉,但图表很难复制/粘贴到文本表中.
我有一个编译的程序的以下VTune配置文件icc --std=c++14 -qopenmp -axS -O3 -fPIC:
在该配置文件中,组装视图中突出显示了两组指令.尽管指令相同且顺序相同,但上部集群比下部集群花费的时间少得多.两个集群都位于同一个函数内,显然都被称为n时间.每次我运行探查器时都会发生这种情况,我现在正在使用Westmere Xeon和Haswell笔记本电脑(使用SSE编译,因为这就是我现在正在瞄准和学习的东西).
我错过了什么?
忽略糟糕的并发性,这很可能是由于笔记本电脑节流,因为它不会发生在桌面Xeon机器上.
我认为这不是微优化的一个例子,因为这三个加在一起相当于总时间的百分之一,我真的对这种行为的可能原因感兴趣.
编辑: OMP_NUM_THREADS=1 taskset -c 1 /opt/intel/vtune...
相同的资料,虽然此次CPI略低.
#include <vector>
#include <iostream>
#include <memory>
using namespace std;
class A
{
static int k;
public:
A(){k++ ; cout << "constructor : " <<k<< endl;};
~A(){k--; cout << "destructor : " << k <<endl;};
void show() { cout<<"current value of k = "<<k<<endl; }
};
int A::k = 0;
int main( )
{
vector<A> test;
test.push_back(A());
test.emplace(test.end(), A());
test[0].show();
cout<<test.size()<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
构造函数:1
析构函数:0
构造函数:1
析构函数:0
析构函数:-1
当前值k = -1
2
析构函数:-2
析构函数:-3
为什么析构函数被调用了太多次,因为它应该被调用两次,因为构造函数只被调用两次?如何避免这种情况?
给定一个包含int(小端)的char缓冲区c.如何将其读作int32_t?
我写了这段代码,但感觉不是惯用的cpp.
int32_t v;
char* p = (char*)&v;
for (int i=0; i < 4; i++) {
*(p+i) = *(c+i);
}
Run Code Online (Sandbox Code Playgroud) 编辑完全忘记提到对我来说很明显的smth:
a_func()要修改的var_xxx,所以使用的是迭代的解决方案const类型不能完全令人满意(虽然他们的想法带来,肯定).
我觉得答案很简单却找不到.
鉴于:
用户类类型(精确地,数学向量对象)的变量(少数,如6,8,10),其中每个变量必须具有由算法定义的唯一名称(以便进行计算)然后独立使用,并能够轻松查阅代码所基于的论文)
做:
在一段代码中,计算并初始化这些变量,并按名称引用它们; 然后在另一段代码中,在扫描中对它们执行操作,而不必复制调用每个变量的操作(即函数)的代码.
代码是这样的:
// in a class declaration
vector_type var_abc, var_efg, var_xyz;
// in a class member function
// "some_math_xxx" pieces are coded inline, not as separate functions
var_abc = /* some_math_abc */;
var_efg = /* some_math_efg */ ;
var_xyz = /* some_math_xyz */ ;
a_func(var_abc); a_func(var_efg); a_func(var_xyz);
Run Code Online (Sandbox Code Playgroud)
我的意思是,我当然可以打a_func(var_xxx)六次或更多次.但是,它对我来说是错的.
想到:
std::array<>指向vars的指针(有点笨拙但有效)此代码无法编译:
for (vector_type& vr : { var_abc, var_efg, var_xyz }) …
引用(感谢作者开发和共享算法!):
https://tavianator.com/fast-branchless-raybounding-box-intersections/
由于现代浮点指令集可以在没有分支的情况下计算最小值和最大值
作者的相应代码就是
dmnsn_min(double a, double b)
{
return a < b ? a : b;
}
Run Code Online (Sandbox Code Playgroud)
我很熟悉例如_mm_max_ps,但这是一个矢量指令.上面的代码显然是用于标量形式.
题:
以防万一:我熟悉在C++中使用min和max函数,相信它是相关的,但不是我的问题.
考虑
volatile int volatile * volatile vip; // (1)
Run Code Online (Sandbox Code Playgroud)
和
volatile int volatile * volatile vipa[10]; // (2)
Run Code Online (Sandbox Code Playgroud)
这两行代码都触发-Wduplicate-decl-specifier(请参阅修订版236142
和gcc7发行说明)。我想知道是否可以volatile在不更改代码语义的情况下从给定代码中删除一些说明符,并且也了解其背后的原因。
因此,存在以下问题:
一个。在(1)中,第一和第二个volatile限定词是否都引用int,因此在gcc术语中是“重复的”?(我在这里查看的是C99 6.7.3.4。)
b。在(2)中,volatile限定词之一是引用数组的类型,而不是int或指针本身,因此C99 6.7.3.8成立:
如果数组类型的规范包括任何类型限定符,则元素类型是合格的,而不是数组类型。
还是volatile(2)中的说明符仅影响int和和pointer类型,而不影响数组的类型?
c。如果b的答案是否定的,我如何声明volatileC99 6.7.3.8中描述的数组类型?它是https://en.cppreference.com/w/c/language/array中描述的语法(引号后面)吗?
限定词-const,restrict或volatile限定词的任何组合,仅在函数参数列表中允许;这限定了将数组参数转换为的指针类型
让我们考虑一下有关C99的问题。如果C11在这方面有任何差异,请进行记录。
我开始学习OpenGL,因为那是我选择的硕士学位课程的一部分.在课堂上,加速3D图形在MS Windows上实现(实际上可能使用DX3d而不是OpenGL,不确定).但是,我已经使用Linux多年了,而且我很肯定它是正确的开发环境,当你可以自由选择时.但是,据我所知,加速3D,特别是驱动程序和硬件支持,在Linux上是一团糟.所以,请帮助我将以下一堆概念组织成一个合理的结构,因为这是我能看到和理解事物的唯一方法.
首先,有司机.NVIDIA和AMD专有,加上"nouveau"和一些开放的Radeon驱动程序,以及一个实验性的AMD开放但仍然是正式的.这似乎很清楚.
其次,有一种叫做"台面"的东西.那是什么?它是仅为免费驱动程序定义的,它是免费驱动程序项目的一部分,还是定义和要求,无论使用何种驱动程序?
在2)的开发中,究竟什么是"opengl"以及它包含在哪里:台面,驱动程序,还有什么?它可以是专有的吗?
最后,鉴于上述三点,"在现代Linux系统上获取和安装OpenGL意味着什么?
使用以下代码,我得到"在此范围内未声明gets()"错误:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
// string str[]={"I am a boy"};
string str[20];`
gets(str);
cout<<*str;
return 0;
}
Run Code Online (Sandbox Code Playgroud) c++ ×6
c ×3
optimization ×3
c++11 ×2
c++14 ×2
api ×1
arrays ×1
assembly ×1
avx ×1
declaration ×1
destructor ×1
drivers ×1
endianness ×1
foreach ×1
intel ×1
intel-vtune ×1
intrinsics ×1
linux ×1
opengl ×1
performance ×1
sse ×1
syntax ×1
templates ×1
tuples ×1
volatile ×1
x86 ×1