我有一个2D矢量,它可用于复数。 仅举例:
vector<vector<double>> Complex;
vector<double> ComplexNumber;
ComplexNumber.push_back(5); // real part
ComplexNumber.push_back(-4); // imag part
Complex.push_back(ComplexNumber); // Complex[i][0] - real part, [i][1] - imag
在我的代码的深度,我需要将我的复杂向量的一部分拉出到其他。 例如,从某个变量(1D向量)中的索引10到18实部复制,并在其他变量(1D向量)中从索引10复制到18个成像部分。 目前我正在以循环方式执行此操作:
for (int j=0; j<=Samples; j++)
{
refRealSignal[j] = ReferenseComplexSignalsSampled[(i*SignalSampleIndex)+j][0] ;
refImagSignal[j] = ReferenseComplexSignalsSampled[(i*SignalSampleIndex)+j][1] ;
}
此代码是分析器显示的整个程序的瓶颈。有没有办法改善它?
小更新:“示例”变量是int
,从8到20,通常是8.变量i
来自外部for循环。
大更新:所以,我推出了2D矢量并用complex
类重写了所有内容。我也在“for”循环中重写了我的mul操作。我不知道为什么,但是从complex.imag
复制需要花费更多时间(更多2),然后从complex.real
部分复制。在所有这些代码性能从一个样本的~5ms增加到一个样本的~1.8ms之后。 (在我重写mul操作并重写整个周期后2.5毫秒,这是一个非常有用的建议,非常感谢)
答案 0 :(得分:1)
如果Samples
很大,您可以保存一些与i
相关的乘法。所以改变这个:
for (int j=0; j<=Samples; j++)
{
refRealSignal[j] = ReferenseComplexSignalsSampled[(i*SignalSampleIndex)+j][0] ;
refImagSignal[j] = ReferenseComplexSignalsSampled[(i*SignalSampleIndex)+j][1] ;
}
到此:
int index;
for(i = ..) { // assuming your code has a for loop for i
index = i*SignalSampleIndex;
for (int j=0; j<=Samples; ++j) // change the ++ as pre-fix
{
refRealSignal[j] = ReferenseComplexSignalsSampled[index+j][0] ;
refImagSignal[j] = ReferenseComplexSignalsSampled[index+j][1] ;
}
}
这样你就可以做1次乘法,而不是2 * Samples
,就像luk32注意到的那样。
另一种方法,如评论中所述,您可以使用类来表示复数。 STL
为此提供了一个类:std::complex
。
然后你会得到一个类型为vector
的{{1}},这会让你的数据更加健壮,这可能会提升std::complex
locality
,caching
将会利用。
你可以这样做:
#include <iostream> // std::cout
#include <complex> // std::complex, std::real
#include <vector> // std::vector
int main ()
{
std::vector<std::complex<double> >complex;
// if you know the amount of your numbers,
// use a reserve(). Assuming you will insert
// 100000 numbers, the code would be
complex.reserve(100000);
for(int i = 0; i < 100000; ++i)
complex[i] = {0.1, 0.2};
std::cout << "Real part of 1st element: " << std::real(complex[0]) << '\n';
return 0;
}
[编辑]
通过使用优化标志,编译器可以执行乘法问题。当使用优化标志编译代码时,请确保对代码进行概要分析。
提示强>:
通常情况下,如果一个部分减慢你的程序速度,有两种方法:(1)使该部分更快,或(2)找到一种方法更少地执行该部分。
(归功于Psyduck,又名Mooling duck)
在您的情况下,您可以尝试我上面提到的建议,以使您的代码更快,但如果您再次考虑您的逻辑并避免/减少您复制的时间,那么将会提高性能。 / p>
答案 1 :(得分:1)
使用std::vector<double>
复数是一个很大的错误。性能。为什么?有几个原因:
分配需要永远。典型值在200 ns以上。
内存分配在堆上。空间方面的开销很大。
内存分配器中的典型开销:两个指针,i。即8或16字节,具体取决于您的架构。
std::vector<>
本身的开销:两个指针,另外8个或16个字节。
std::vector<>
的总体配置:典型实现永远不会仅为两个元素分配内存。我估计这个开销至至少六个元素(八个元素最小分配)。这将导致48字节的开销。
因此,您最终会使用80字节来存储适合16的内容。
这很重要,因为这意味着您的缓存/内存总线必须完成五倍的工作!
内存分配在堆上。这意味着您的复杂数字可能分散。这是缓存效率的另一个打击。
如果你想要快,请使用带有两个元素的数组(如果使用C风格数组或C ++ std::array<>
无关紧要)或将复杂类型定义为普通旧数据{{1} }。所有三个选项都具有相同的内存布局,因此在性能上应该相同。但我更喜欢struct
方法,因为它允许你重载运算符,这对数学类型如复数,向量,四元数等很好。