为什么这些函数的表现如此不同?

问题描述 投票:0回答:1

我制作了两个用于将向量相加的函数,以便我可以将正弦波相加,其中一个使用 + 运算符相加,另一个使用 lambda 函数将它们相加,这使我更容易为多个操作创建函数。其中一个需要 5 微秒,另一个需要大约 17000 秒。

#include <iostream>
#include <vector>
#include <stdint.h>
#include <numbers>
#include <functional>
#include <chrono>
#include <cmath>

using i16 = int16_t;

constexpr float sample_rate = 44100;

std::vector<i16> sineWave(float frequency, float amplitude, float duration){
    int sampleCount = duration*sample_rate;
    std::vector<i16> samples(sampleCount);
    
    for(float i = 0;i<sampleCount;i++){
        samples[i] = static_cast<i16>(std::sin(2.0f*std::numbers::pi*frequency*(i/sample_rate))*amplitude);
    }
    
    return samples;
    
}

std::vector<i16> waveAdd(std::vector<i16>& wave1, std::vector<i16>& wave2){
    if(wave1.size() > wave2.size()){
        wave1.resize(wave2.size());
    }
    else if(wave2.size() > wave1.size()){
        wave2.resize(wave1.size());
    }
    
    std::vector<i16> final(wave1.size());
    for(size_t i = 0;i<wave1.size();i++){
        final[i] = wave1[i]+wave2[i];
    }
    return final;
}

std::vector<i16> waveOperation(std::vector<i16>& wave1, std::vector<i16>& wave2, std::function<i16(i16,i16)> operation){
    if(wave1.size() > wave2.size()){
        wave1.resize(wave2.size());
    }
    else if(wave2.size() > wave1.size()){
        wave2.resize(wave1.size());
    }
    
    std::vector<i16> final(wave1.size());
    for(size_t i = 0;i<wave1.size();i++){
        final[i] = operation(wave1[i],wave2[i]);
    }
    return final;
}

int main(){
    
    auto a = sineWave(10000,1000,20);
    
    auto b = sineWave(1000,2000,20);
    
    auto start1 = std::chrono::high_resolution_clock::now();
    auto d = waveAdd(a,b);
    auto end1 = std::chrono::high_resolution_clock::now();
   
    auto start2 = std::chrono::high_resolution_clock::now();
    auto c = waveOperation(a,b,[] (i16 a, i16 b) { return (a+b); } );
    auto end2 = std::chrono::high_resolution_clock::now();
    
    auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(end1-start1);
    auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>(end2-start2);
    
    std::cout << "+ operator: " << duration1.count() << std::endl;
    std::cout << "lambda: " << duration2.count() << std::endl; 
    
}

有没有一种方法可以解决这个问题,或者最好只创建一个均衡长度辅助函数,然后复制粘贴并更改运算符?

我确实在 cpp.sh 中运行了它,而不是在我的机器上运行,但我认为这对所需的时间没有太大影响。

c++ optimization vector
1个回答
0
投票

有没有一种方法可以解决这个问题,或者最好只创建一个均衡长度辅助函数,然后复制粘贴并更改运算符?

首先,了解

std::function
会带来运行时性能成本。 它的类型擦除不是免费的!

其次,您的 lambda 函数将编译时信息移至运行时。 编译器可以优化多个添加,但优化对任意

std::function::operator()
的多个调用会困难得多。

如果您在编译时知道想要什么 lambda,请将其作为模板参数传递!

template<auto operation>
std::vector<i16> waveOperation(std::vector<i16>& wave1, std::vector<i16>& wave2){
    if(wave1.size() > wave2.size()){
        wave1.resize(wave2.size());
    }
    else if(wave2.size() > wave1.size()){
        wave2.resize(wave1.size());
    }
    
    std::vector<i16> final(wave1.size());
    for(size_t i = 0;i<wave1.size();i++){
        final[i] = operation(wave1[i],wave2[i]);
    }
    return final;
}

查看新结果

© www.soinside.com 2019 - 2024. All rights reserved.