C++ 如何组织时间密集型代码以避免开销
我试图教会自己如何编写更快的代码(使用更少指令的代码)。我想创建一个人工神经网络(ANN)。如果您对ANN一无所知,您可能仍然能够帮助我,因为我的问题更多地涉及编写比ANN更快的代码。基本上,我将有一个大数组的双打,我需要执行大量的数学。我可以这样分配阵列:C++ 如何组织时间密集型代码以避免开销,c++,arrays,memory,optimization,memory-management,C++,Arrays,Memory,Optimization,Memory Management,我试图教会自己如何编写更快的代码(使用更少指令的代码)。我想创建一个人工神经网络(ANN)。如果您对ANN一无所知,您可能仍然能够帮助我,因为我的问题更多地涉及编写比ANN更快的代码。基本上,我将有一个大数组的双打,我需要执行大量的数学。我可以这样分配阵列: class Network { double *weights; double *outputs; public: Network() { } Network(int * size
class Network {
double *weights;
double *outputs;
public:
Network()
{
}
Network(int * sizes, int numofLayers)
{
int sum = 0;
int neuron_count = 0;
// this just ensures my weight array is the right size
for(int i = 0; i < numofLayers-1; i++)
{
neuron_count += sizes[i];
sum = sum + sizes[i]*sizes[i+1];
}
neuron_count += sizes[numofLayers-1];
weights = new double[sum];
outputs = new double[neuron_count];
}
~Network()
{
delete[] weights;
delete[] outputs;
}
};
类网络{
双倍*重量;
双*输出;
公众:
网络()
{
}
网络(整数*大小,整数层)
{
整数和=0;
int神经元计数=0;
//这只是确保我的权重数组大小正确
对于(int i=0;i
然而,我不喜欢这个,因为我使用“new”,我知道我以后可能会遇到一系列内存管理问题。我知道堆栈分配更快,如果我能根据以下摘录提供帮助,我不应该使用动态内存:
“动态内存分配由操作员new和delete完成
或者使用malloc和free函数。这些运算符和函数
消耗大量时间。内存的一部分称为堆
为动态分配保留。堆可以很容易地
当分配不同大小的对象并
以随机顺序释放。堆管理器可能会花费大量时间
清理不再使用的空间并搜索空闲空间
空间。这称为垃圾收集。分配的对象
按顺序存储的数据不一定按顺序存储在内存中
当堆变大时,可能分散在不同的位置
碎片化。这使得数据缓存效率低下”
优化C++软件,Windows,Linux优化指南
以及Agner Fog的Mac平台
但是,数组权重和输出将被我想在类网络中创建的许多函数使用;如果它们是本地的,并且被解除分配,那就行不通了。我觉得要么使用新的关键字,要么只是为几乎整个神经网络制作一个巨大的函数
在正常情况下,我会说可读性对于维护代码更为重要,但我并不担心这一点,因为这更需要学习如何编写快速代码。如果为耗时的算法编写代码的人为了使事情变得最快而编写大函数,那没关系。我只是想知道
另一方面,如果我的数组只分配一次,并且将在整个程序中使用,那么使用堆分配是否更明智,因为有问题的开销应该只发生一次?然后集中精力在数学密集型代码中使用内部函数或其他东西。是否还有其他缺点,例如,如果我经常访问堆,以便将堆中的内存移动到缓存中,这是否比经常访问堆栈上的内存,以便将堆栈移动到缓存中更密集(即使堆应该保持不变)?写快速代码的人总是绝对避免新代码吗?如果是这样的话,我有什么办法可以这样组织我的程序,并且仍然保持用户指定的任意大小的数组?堆内存中没有什么不好或慢的东西。然而,在某些情况下,你应该在使用它的方式上小心。真正影响性能的一个主要问题是,堆内存中分散着许多小对象(因为每次分配都会在内存中的任何位置放置一个新对象)。在这种情况下会发生这种情况,例如:
for(int i = 0; i < some_size; ++i)
some_array = new MySmallObject;
for(int i=0;i
这里的问题是,如果长期使用some_array
执行许多操作,缓存命中率可能会非常低(这是在现代硬件上与性能抗争时可以使用的主要参数之一),最终导致性能下降。这是因为每次对内存的访问某些数组[i]
可能需要访问分散的内存位置,并且无法适应缓存预测算法
另一个问题是长时间不使用分配的内存,并且在应用程序中长时间经常重新分配内存。这也会影响您的性能,因为动态内存分配操作并不简单,它源于动态内存的性质。此内存不知道要分配的数据以及何时分配这些数据。因此,简单地说,这是一个记忆片段表,它知道哪些忙,哪些不忙。现在,你经常分配许多小对象,删除一些旧对象。那是无法控制的。根据动态内存的实现,可能会出现内存碎片化等操作,这可能取决于分配/取消分配内存的频率。当然,这也会影响性能
这是与两个动态内存分配相关的两个性能杀手。一个合法的问题出现了,该怎么办?许多问题可以通过重新设计程序或/或重新设计算法来解决。但是,在某些情况下不可能这样做,那么选项将是自定义分配器。分配器是提供分配/释放内存操作的类型。这些分配器是模板参数和构造函数参数,例如,遍布std
容器,如vector
、string
等。另一个选项是重载全局或成员运算符