构造函数初始化速度

时间:2018-03-07 10:05:03

标签: c++11 visual-c++ visual-studio-2015 constructor move-semantics

我运行了一些测试来验证我对构造函数速度的先入为主的想法,但结果与我的预期有很大不同。难道我做错了什么?我错过了什么? 我没有使用MVS 2015而没有进行优化(但结果总是等价的并不重要。)

def display_mask_superpixel(image):

    image = cv2.imread(image)
    segments = slic(img_as_float(image), n_segments=50, sigma=5)
    # show the output of SLIC
    fig = plt.figure("Superpixels")
    ax = fig.add_subplot(1, 1, 1)
    ax.imshow(mark_boundaries(img_as_float(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)), segments))
    plt.axis("off")
    plt.show()
    plt.cla()
    plt.close()

    for (i, segVal) in enumerate(np.unique(segments)):
        # construct a mask for the segment
        print("[x] inspecting segment %d" % (i))
        mask = np.zeros(image.shape[:2], dtype="uint8")
        mask[segments == segVal] = 255

        # show the masked region
        cv2.imshow("Mask", mask)

        cv2.imshow("Applied", cv2.bitwise_and(image, image, mask=mask))
        cv2.waitKey(0)

List_of images=images

for image in list_of_images:
    display_mask_superpixel(image)

// 1 - 总是比其他人更快。

// 2 - 略慢于1(可忽略不计!!)。???

// 3 - 比1. ???多花费50%的时间。

我使用小字符串(8字节),1K,2K字符串大小运行测试。 我期待// 2 ctor是最快的,而不是期望// 3花了这么多时间。 最后一个问题是我在// 3 ctor做什么是合法的?

更新 这是我写的代码

class Person
{   using ushort = unsigned short;
    string  name_;
    ushort  age_;    
public: 
    explicit Person(const string &name, ushort age) //1
    {   name_ = name;
        age_  = age;
    }        
    explicit Person(const string &name,ushort age) : name_{name},age_{age} //2
    {   
    }        
    explicit Person(string name, ushort age) : name_{ std::move(name) }, age_{ age } //3
    {   
    }
};

我被MVS的 debug 版本弄错了,即使使用相同的项目设置,它也会显示与 release 版本截然不同的结果!我的错误......

4 个答案:

答案 0 :(得分:0)

没有优化的基准测试毫无意义。

你传递的字符串为name?一个非常重要的因素是字符串的长度,以及它是否会触发SBO(小缓冲区优化)。

如果字符串足够短,则移动速度不会比副本快。

此外,您的基准测试结果如何?可能是您的基准测试代码存在缺陷。

答案 1 :(得分:0)

我也希望// 2是最快的,让我们来看看差异构造函数的作用。

  • // 1:name_是默认构造的,然后复制已分配。
  • // 2:name_是复制构造的。
  • // 3:名称是复制构造的,然后name_是移动构造的。

随着默认构造变得更加昂贵,// 1和// 2之间的差异将会增大。

// 3是有效的,因为参数名称只存在于构造函数中,所以我们可以通过移动构造名称_来窃取内部。

Nicolai Josuttis在2017年CppCon上有一个great talk

答案 2 :(得分:0)

当我尝试对您的代码进行基准测试时,我得到了一些不同的结果。 该基准测试在AWS Machines池上运行,使用Clang 5.0 C ++ 17 -O3编译。

#include <string>

class Person1
{   using ushort = unsigned short;
    std::string  name_;
    ushort  age_;    
public: 
    explicit Person1(const std::string &name, ushort age) //1
    {   name_ = name;
        age_  = age;
    }  
};

class Person2
{   using ushort = unsigned short;
    std::string  name_;
    ushort  age_;    
public:            
    explicit Person2(const std::string &name,ushort age) : name_{name},age_{age} //2
    {   
    }    
};

class Person3
{   using ushort = unsigned short;
    std::string  name_;
    ushort  age_;    
public:    
    explicit Person3(std::string name, ushort age) : name_{ std::move(name) }, age_{ age } //3
    {   
    }
};


static void CreatePerson1(benchmark::State& state) 
{
   for (auto _ : state) {
       Person1 person("Hello World!!!!!!!!!!!!", 10);
   }
}
BENCHMARK(CreatePerson1);

static void CreatePerson2(benchmark::State& state) 
{
    for (auto _ : state) {
       Person2 person("Hello World!!!!!!!!!!!!", 10);
    }
}
BENCHMARK(CreatePerson2);

static void CreatePerson3(benchmark::State& state) 
{
    for (auto _ : state) {
       Person3 person("Hello World!!!!!!!!!!!!", 10);
    }
}
BENCHMARK(CreatePerson3);
  1. 使用一个小字符串(8个字节),第二个构造函数最快,然后是第三个。请在此处查看结果Quick C++ Benchmarks

  2. 使用更大的字符串(20个字节),第三个构造函数最快,然后是第二个构造函数。请在此处查看结果Quick C++ Benchmarks

答案 3 :(得分:-1)

您在第三种情况下复制。相反,尝试这样的事情:

class Person
{   using ushort = unsigned short;
    string  name_;
    ushort  age_;    
public:     
    explicit Person(string&& name, ushort age) : name_{ std::move(name) }, age_{ age } //3
    {   
    }
    explicit Person(const string &name, ushort age) //1
    {  
        name_ = name;
        age_  = age;
    }        
    explicit Person(const string &name,ushort age) : name_{name},age_{age} //2
    {   
    }  
};

R值的使用必须提高性能。

或者你可以为aboce r-value和l-value创建一个构造函数,如下所示:

class Person
{   using ushort = unsigned short;
    string  name_;
    ushort  age_;    
public:   
    template<typename T>  
    explicit Person(T&& name, ushort age) : name_{ std::forward<T>(name) }, age_{ age } //3
    {   
    }

};