我需要创建一种共享对象(无论出于何种原因)。它不仅限于单线程使用。通常在这种情况下,可以采用互锁操作(例如Win32上的InterlockedIncrement
和InterlockedDecrement
)。
尽管对象引用计数应该在任何场景中都能正常工作,但我希望针对单线程使用进行优化。互锁操作比标准算术操作重得多。根据我的测量结果,一个互锁操作(发出完整的内存屏障)大约需要40个CPU周期才能完成#34;典型的" CPU,而标准算术值低于任何测量精度(由于CPU缓存)。
在内存分配方面,有类似的技术。存在堆实现,例如" TCMalloc",它由集中的内存分区机制组成,由适当的同步对象保护,加上每线程缓存。在最常见的情况下,在每线程缓存上分配/释放的内存,根本不涉及任何互锁操作,加上CPU缓存的概率很高。
因此,我有可能为参考支持对象做类似的事情。任何想法如何实现这一目标?原创的想法也很受欢迎。
在我的场景中可以延迟实际的对象破坏一段时间,如果这样可以提高性能。
答案 0 :(得分:1)
我不会打扰。我刚刚运行了这个基准:
#include<stdio.h>
#define SIZE 1000000
static __inline__ unsigned long long rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
void print_avg(const char *str, const int *diff, int size)
{
int i;
long sum = 0;
int max = -1, min = 10000;
for(i = 0; i < size; i++)
{
int t = diff[i];
sum += t;
if (t > max) max = t;
if (t < min) min = t;
}
printf("%s average =%f clocks, max =%d, min =%d\n", str, (double)sum / size, max, min);
}
int main()
{
unsigned long long a, b;
int diff[SIZE];
int value = 0;
int i;
for(i = 0; i < SIZE; i++)
{
a = rdtsc();
__sync_fetch_and_add(&value, 2);
b = rdtsc();
diff[i] = (int)(b - a);
}
print_avg("Locked", diff, SIZE);
for(i = 0; i < SIZE; i++)
{
a = rdtsc();
value += 2;
b = rdtsc();
diff[i] = (int)(b - a);
}
print_avg("Not locked", diff, SIZE);
return 0;
}
使用gcc -O2编译它会得到以下结果:
Locked average =105.672402 clocks, max =38756, min =86
Not locked average =80.540389 clocks, max =23433, min =73
我跑了几次,结果每次非常相似。请忽略max的最大值 - 当处理器中断或其他什么时 - 它来自我为不同目的编写的一些代码,我只是回收了这个测试。这种小差异应该适用于所有现代处理器(Intel iCore和AMD Athlon64以及那些代)
除非由于某种原因您的编译器没有内联InterlockedIncrement,否则在代码上添加if语句很可能至少花费5个周期,因此您最多可以节省10个周期。希望你做的不是增加和减少参考计数器。
编辑:添加内存屏障也不会产生很大的影响 - 大约10个周期。
不可否认,如果我在第二个循环中添加十个加法,则每个循环大约需要五个时钟周期(平均每个加法半个时钟),其中锁定加法每个加法大约需要20个时钟。在我看来,仍然不值得添加if语句。但是如果你想添加“if(nr_threads == 1)a = a + 1;否则a = __sync_fetch_and_add(a,1);”,[或者无论你需要做什么]我都不会阻止你。但请确保您对整个应用程序进行基准测试,并确保其提高1%以上 - 我对此表示怀疑。请回来告诉我们有什么区别。我在Linux内核的“deallocate page-table entries”中添加的if语句使得它慢了2-5%,所以不值得。但是如果你在代码中发现它是值得的,那就是我的客人吧。我是根据经验说话,而且我有数字来展示它,但如果你想为自己尝试,那么为什么不这样做。