为什么Valarray在Visual Studio 2015上如此慢
Why is valarray so slow on Visual Studio 2015?
为了加快库中的计算,我决定使用std::valarray
类。文档说:
std :: valarray和助手课程被定义为没有确定的 混叠的形式,从而使这些班级的操作成为 优化与C中关键字限制的效果相似 编程语言。此外,采用的功能和操作员 允许Valarray参数返回代理对象 编译器可以优化诸如v1 = a * v2之类的表达式 v3;作为执行v1 [i] = a * v2 [i] v3 [i]的单个循环;避免任何临时或多次通过。
这正是我所需要的。当我使用G 编译器时,它正如文档中所述的工作。我已经开发了一个简单的示例来测试std::valarray
性能:
void check(std::valarray<float>& a)
{
for (int i = 0; i < a.size(); i++)
if (a[i] != 7)
std::cout << "Error" << std::endl;
}
int main()
{
const int N = 100000000;
std::valarray<float> a(1, N);
std::valarray<float> c(2, N);
std::valarray<float> b(3, N);
std::valarray<float> d(N);
auto start = std::chrono::system_clock::now();
d = a + b * c;
auto end = std::chrono::system_clock::now();
std::cout << "Valarr optimized case: "
<< (end - start).count() << std::endl;
check(d);
// Optimal single loop case
start = std::chrono::system_clock::now();
for (int i = 0; i < N; i++)
d[i] = a[i] + b[i] * c[i];
end = std::chrono::system_clock::now();
std::cout << "Optimal case: " << (end - start).count() << std::endl;
check(d);
return 0;
}
在G 上,我得到了:
Valarr optimized case: 1484215
Optimal case: 1472202
似乎所有操作d = a + b * c;
确实都放在一个周期中,这在保持性能的同时简化了代码。但是,当我使用Visual&nbsp; Studio; 2015年时,这无效。对于相同的代码,我得到:
Valarr optimized case: 6652402
Optimal case: 1766699
差异几乎是四次;没有优化!为什么std::valarray
在2015年的Visual&nbsp" Studio&nbsp"中不需要工作?我做的一切正确吗?我如何解决问题而不放弃std::valarray
?
我做的一切正确吗?
您正在做正确的事情。问题是在Visual Studio std::valarray
实现中。
为什么
上不需要工作std::valarray
在Visual&nbsp; Studio&nbsp; 2015?
只需打开任何valarray
操作员的实现,例如operator+
。您会看到类似(宏扩展之后(:
template<class _Ty> inline
valarray<_Ty> operator+(const valarray<_Ty>& _Left,
const valarray<_Ty>& _Right)
{
valarray<TYPE> _Ans(_Left.size());
for (size_t _Idx = 0; _Idx < _Ans.size(); ++_Idx)
_Ans[_Idx] = _Left[_Idx] + _Right[_Idx];
return (_Ans)
}
您可以看到,创建一个新对象,其中复制操作的结果。确实没有优化。我不知道为什么,但这是事实。看起来在Visual Studio中,仅添加std::valarray
才能兼容。
要进行比较,请考虑GNU实施。如您所见,每个操作员返回仅包含操作但不包含数据的模板类_EXPR。实际计算是在分配运算符中执行的,更具体地说是在__valarray_copy函数中执行的。因此,在执行作业之前,所有操作均在代理对象_Expr
上执行。只有调用operator=
,就可以在单个环中执行的_Expr
中存储的操作。这就是为什么您获得G 的好结果的原因。
如何解决问题?
您需要在Internet上找到合适的std::valarray
实现,也可以自己编写。您可以将GNU实现作为示例。
- Visual Studio 2015:Extern "C" 和 "export" 关键字
- Qt Visual Studio 2015 加载项编译问题
- 包含在 <WinSock2> Visual Studio 2015 中时出现错误
- 在 Windows 10 上的 Visual Studio 2015 中使用 _open 和 _setmode
- 如何在不进入 Visual Studio 2015 中的外部库的情况下单步执行我的代码 (F11)
- c++ Visual Studio 2015 快捷方式,用于从选择代码中生成功能
- Visual Studio 2015资源视图和资源编译器使用不同的方法在项目目录中查找图标文件.如何修复
- Visual Studio 2015 中的调试速度很慢 -- 无法关闭页面堆?
- 在 C++ 中使用带有正则表达式的 G++ 和 Visual Studio 14 2015 编译器时会产生不同的结果
- 安装 SFML 后 Visual Studio 2015 中出现错误
- WinDBG适用于从Visual Studio 2015保存的转储,但不适用于任务管理器。显示异常代码"not found"
- 在Visual Studio 2017上使用VC++ 2015工具链时缺少ATL标头
- Visual Studio 2015 安装问题
- 迁移到 Visual Studio 2015 时 ATL 不起作用
- 使用 Visual Studio Shell (隔离) 2015 编译
- Qt5.9.1 和 Visual Studio 2015 添加了 Qt WebEngine 模块
- 外部 "C" Visual Studio 2015 中的显式类型错误,DLL 测试代码
- CMake 和 Visual Studio 2015 - C 编译器 cl.exe 无法编译简单的测试程序
- 如何在 Linux 中运行 Visual Studio 2015 托管 c++ 测试函数?
- Visual Studio 2015:在远程编译(在Raspberry上)和本地编译(在Windows上)之间切换