只是想知道是否有人会为我确认一些别名规则.
我知道别名(即加载存储问题)可能导致以下类型的代码不是最理想的,因为我们不能假设x, y, z不重叠:
// case 1:
void plus(size_t n, double *x, double *y, double *z)
{
for (size_t i = 0; i != n; ++i)
z[i] = x[i] + y[i];
}
Run Code Online (Sandbox Code Playgroud)
我知道有一个C关键字__restrict提示编译器它不应该考虑重叠的情况,因此可能生成更好的代码:
// case 2:
void plus(size_t n, double *__restrict x, double *__restrict y, double *__restrict z)
{ // as above... }
Run Code Online (Sandbox Code Playgroud)
但是,别名如何使用C++样式代码,我们将处理通过引用传递的容器对象,而不是上面带有原始指针的C类示例?
例如,我假设如果我们执行以下操作会出现别名问题:
// case 3:
void plus(std::vector<double> &x, std::vector<double> &y, std::vector<double> &z)
{ // similar to above... }
Run Code Online (Sandbox Code Playgroud)
并且转移到一个不那么简单的例子,如果容器中的底层数据类型不同,它会有什么不同吗?在实现级别,大多数容器使用指针动态管理存储,因此我不清楚编译器如何确保以下不是别名: …
我有一个三角网格.假设它看起来像一个凹凸不平的表面.我希望能够找到落在网格周围边缘的所有边缘.(忘记内顶点)
我知道我必须找到只连接到一个三角形的边缘,并将所有这些收集在一起,这就是答案.但我想确保这些边的顶点按顺时针顺序排列.
我想这样做是因为我想在网格外部得到一条多边形线.
我希望这很清楚,可以理解.在某种意义上,我试图"去三角化"网格.哈!如果有这样一个词.
由于几天前的这个问题,有一些事情一直困扰着我对于野外std::deque::push_back/push_front实际std::deque实施的复杂性要求.
上一个问题的结果是这些操作需要具有O(1)最差的案例复杂性.我确认这确实是这样的c++11:
从23.3.3.4 deque修饰符,参考insert,push/emplace前/后
复杂性:复杂性是插入元素数量的线性加上到双端队列开始和结束距离的较小者.在双端队列的开头或末尾插入单个元素总是需要恒定的时间并导致对T的构造函数的单个调用.
这与O(1)索引,通过operator[]等的复杂性要求相结合.
问题是实现并不严格满足这些要求.
在这两个方面msvc与gcc所述std::deque的实施是一个阻塞数据结构,由指针的动态阵列的至(固定大小)的块,其中每个块中存储有数量的数据元素.
在最坏的情况下,push_back/front etc可能需要一个额外的块将被分配(这是精-固定大小的分配是O(1)),但它也可以要求块指针的动态阵列被调整大小-这不是很好的,因为这是O(m)其中m是块数,在一天结束时O(n).
显然,这仍然是分摊的O(1)复杂性,因为通常m << n它在实践中会非常快.但似乎存在一致性问题?
作为进一步的点,我看不出你如何能设计一个数据结构,严格同时满足O(1)两个复杂性push_back/front etc和operator[].您可以拥有块指针的链接列表,但这并不能提供所需的operator[]行为.真的可以吗?
是否有任何保证realloc()将始终缩小缓冲区?以下是:
new_ptr = (data_type *) realloc(old_ptr, new_size * sizeof(data_type));
Run Code Online (Sandbox Code Playgroud)
如果new_size <old_size,则总是会给new_ptr == old_ptr(当然除了new_size == 0).它对我来说似乎是明智的,但它很好奇标准是否强制执行它.
我正在研究非POD数据类型数组的重新分配,如果上述行为得到保证,则认为以下策略可能至少允许有效"缩小":
if (new_size > old_size)
{
// malloc() a new buffer
// use placement copy constructor to copy old objects over
// free() old buffer
}
else
if (new_size < old_size)
{
// explicit destruction of unneeded objects
// realloc() buffer
}
Run Code Online (Sandbox Code Playgroud)
即使数据类型有自引用/指针或其他什么,我希望就地"缩小"会很强大...
我最近惊讶地注意到,/GS在某些情况下,在MSVC++ 2010中使用(启用缓冲区安全检查)进行编译似乎对运行时性能产生了不可忽视的影响.有没有其他人有这种经验??
对于大型科学应用程序(网格生成库),似乎编译/GS-可以使我的测试套件中的几个大基准测试的运行时间几乎提高10%("大"是> = 1秒的价值运行)./GS默认情况下,在MSVC++ 2010中的所有优化级别都处于启用状态.
我必须承认,我之前从未过多地关注过这个选项,而且我想要澄清它实际上做了什么.在线文档似乎广泛谈论字符串缓冲区,但由于我不使用string或char[]缓冲任何地方我必须遗漏一些东西.
这段(来自在线文档)似乎表明我看到的性能下降有点不寻常:
必须在应用程序中使用安全检查进行性能权衡.Visual C++编译器团队专注于降低性能下降.在大多数情况下,性能不应降低2%以上.实际上,经验表明大多数应用程序(包括高性能服务器应用程序)都没有注意到任何性能影响.
当然,我可以关闭它,并获得更快的代码,但我想在我这样做之前理解其含义.
我认为用于存储指针之间差异的正确类型是ptrdiff_t.
因此,我对我STL(msvc 2010)实现它的std::vector::size()功能的方式感到困惑.返回类型是size_t(这是标准规定的,据我所知),但它被计算为指针的差异:
// _Mylast, _Myfirst are of type pointer
// size_type, pointer are inherited from allocator<_Ty>
size_type size() const
{
return (this->_Mylast - this->_Myfirst);
}
Run Code Online (Sandbox Code Playgroud)
很显然,有一个位的元魔,为了继续,以确定到底是什么类型的size_type和pointer是.为了"确定"它们是什么类型我检查了这个:
bool bs = std::is_same<size_t, std::vector<int>::size_type>::value;
bool bp = std::is_same<int * , std::vector<int>::pointer>::value;
// both bs and bp evaluate as true, therefore:
// size_type is just size_t
// pointer is just int*
Run Code Online (Sandbox Code Playgroud)
编译具有以下/Wall给我signed-to-unsigned mismatch了mysize2,但没有任何警告的mysize1: …
几乎与标题一样.
规范std::vector<T>::resize似乎要求src通过值传递对象:
void resize(size_type n, T src = T() );
Run Code Online (Sandbox Code Playgroud)
为什么不是对这里使用的常量对象的引用呢?
void resize(size_type n, T const& src = T() );
Run Code Online (Sandbox Code Playgroud)
例如,在这个问题中,由于在堆栈上创建了临时对象,传值方面似乎会导致堆栈溢出问题.
如果引用了一个引用src,我们至少可以通过在堆上分配一个临时引用来解决问题::resize().
它似乎::resize()与其他成员函数不一致std::vector.例如,构造函数按预期获取src对象const&:
vector (size_type n, T const& src = T(), Allocator const& = Allocator() );
Run Code Online (Sandbox Code Playgroud)
编辑:我挖出c++03标准,并仔细检查上面的函数原型没有错误引用...
有没有人有使用 Core 2 Duo 处理器的预取指令的经验?
我一直在为一系列 P4 机器成功使用(标准?)预取集(prefetchnta、prefetcht1等),但是在 Core 2 Duo 上运行代码时,prefetcht(i)指令似乎什么都不做,而且prefetchnta指令更少有效的。
我评估性能的标准是 BLAS 1 向量向量 (axpy) 操作的计时结果,当向量大小足以实现缓存外行为时。
英特尔是否引入了新的预取指令?
一些二叉树数据结构(例如Splay树)将在读取上重新平衡以将最近访问的项目移动到根,从而可以减少随后的查找时间.
标准容器(std::map,std::set)是否允许这样做?
至少有一个问题是线程安全.以前,我认为只要你只对标准容器进行只读操作,就可以安全地从多个线程执行此操作而不引入互斥锁/锁等等.也许我需要重新考虑一下?
我知道通常使用红黑树作为标准树容器,并且这些数据结构通常不会在读取时修改.但是,修改过的假设实现是否符合要求?
我的c ++ - standards-foo需要改进,但我不确定当前的标准是否解决了容器的线程安全问题.这有c++0x什么不同吗?
c++ ×7
algorithm ×1
assembly ×1
blas ×1
c++11 ×1
containers ×1
geometry ×1
mesh ×1
prefetch ×1
splay-tree ×1