我有一个Process()
函数在我的DLL(VST插件)中被称为非常重的,在DAW(主机软件)中加载,例如:
for (int i = 0; i < nFrames; i++) {
// ...
for (int voiceIndex = 0; voiceIndex < PLUG_VOICES_BUFFER_SIZE; voiceIndex++) {
Voice &voice = pVoiceManager->mVoices[voiceIndex];
if (voice.mIsPlaying) {
for (int envelopeIndex = 0; envelopeIndex < ENVELOPES_CONTAINER_NUM_ENVELOPE_MANAGER; envelopeIndex++) {
Envelope &envelope = pEnvelopeManager[envelopeIndex]->mEnvelope;
envelope.Process(voice);
}
}
}
}
void Envelope::Process(Voice &voice) {
if (mIsEnabled) {
// update value
mValue[voice.mIndex] = (mBlockStartAmp[voice.mIndex] + (mBlockStep[voice.mIndex] * mBlockFraction[voice.mIndex]));
}
else {
mValue[voice.mIndex] = 0.0;
}
}
它主要占用主机内2%的CPU(这很好)。
现在,如果我稍微将代码更改为此(基本上是增量和赋值):
void Envelope::Process(Voice &voice) {
if (mIsEnabled) {
// update value
mValue[voice.mIndex] = (mBlockStartAmp[voice.mIndex] + (mBlockStep[voice.mIndex] * mBlockFraction[voice.mIndex]));
// next phase
mBlockStep[voice.mIndex] += mRate;
mStep[voice.mIndex] += mRate;
}
else {
mValue[voice.mIndex] = 0.0;
}
// connectors
mOutputConnector_CV.mPolyValue[voice.mIndex] = mValue[voice.mIndex];
}
CPU达到6/7%(注意,那些var不与代码的其他部分交互,或者至少我认为如此)。
我能想到的唯一原因是对指针的访问很重?如何减少这个CPU数量?
这些数组是基本的双“指针”数组(最轻的C ++ container
):
double mValue[PLUG_VOICES_BUFFER_SIZE];
double mBlockStartAmp[PLUG_VOICES_BUFFER_SIZE];
double mBlockFraction[PLUG_VOICES_BUFFER_SIZE];
double mBlockStep[PLUG_VOICES_BUFFER_SIZE];
double mStep[PLUG_VOICES_BUFFER_SIZE];
OutputConnector mOutputConnector_CV;
有什么建议吗?
答案 0 :(得分:2)
你可能会认为“指针数组”是最轻的容器。但CPU并不考虑容器。他们只是通过指针读取和写入值。
这里的问题很可能是你知道两个容器没有重叠(没有“子容器”)。但是编译器可能没有告诉CPU。写入mBlockStep
可能会影响mBlockFraction
。编译器没有运行时值,因此需要处理它的情况。这意味着引入更多的内存读取,并减少寄存器中值的缓存。
答案 1 :(得分:1)
vector
。Process
函数中,从该向量中获取单个元素,并使用其参数。在高速缓存行/指令级别,所有项目(有效地)将被带入本地高速缓存(L1),作为连续的数据元素(结构的成员)。使用struct类型的引用或指针来避免复制。double
。 修改强>:
struct VoiceInfo
{
double mValue;
...
};
VoiceInfo voices[PLUG_VOICES_BUFFER_SIZE];
// Or vector<VoiceInfo> voices;
...
void Envelope::Process(Voice &voice)
{
// Get the object (by ref/pointer)
VoiceInfo& info = voices[voice.mIndex];
// Work with reference 'info'
...
}