我运行了一些测试来验证我对构造函数速度的先入为主的想法,但结果与我的预期有很大不同。难道我做错了什么?我错过了什么? 我没有使用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 版本截然不同的结果!我的错误......
答案 0 :(得分:0)
没有优化的基准测试毫无意义。
你传递的字符串为name
?一个非常重要的因素是字符串的长度,以及它是否会触发SBO(小缓冲区优化)。
如果字符串足够短,则移动速度不会比副本快。
此外,您的基准测试结果如何?可能是您的基准测试代码存在缺陷。
答案 1 :(得分:0)
我也希望// 2是最快的,让我们来看看差异构造函数的作用。
随着默认构造变得更加昂贵,// 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);
使用一个小字符串(8个字节),第二个构造函数最快,然后是第三个。请在此处查看结果Quick C++ Benchmarks
使用更大的字符串(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
{
}
};