程序性能优化手段-避免伪共享

  当分配数个变量或者定义数个全局变量时,这些不同用途的变量很可能会被分配到很近的地址空间上,会导致CPU在读取时,他们会处在同一个Cache line中。如果这时一个CPU上的线程在操作其中一个变量,而另一个CPU上的线程在读另一个变量,将导致读线程CPU不得不和写线程CPU进行一次缓存同步后才能将数据读取出来,这会导致增加缓存开销和总线开销,降低程序效率。这就是并发编程中常碰到的False sharing的问题。详细内容可以参看这篇
  还是拿上一篇文章的代码做测试:

#include "stdafx.h"
#include "windows.h"

PLONG pData1;
PLONG pData2;

DWORD
WINAPI 
Thread1(
    LPVOID lpThreadParameter
) {
    DWORD Start = GetTickCount();

    for (ULONG i = 0;i < 10000000;i++)
        InterlockedAdd(pData1, 1);

    printf("Time:%d\n", GetTickCount() - Start);
    return 1;
}

DWORD
WINAPI
Thread2(
    LPVOID lpThreadParameter
) {
    for (ULONG i = 0;i < 10000000;i++)
        InterlockedAdd(pData2, 1);

    return 1;
}

int main()
{

    DWORD Tid;

    pData1 = (PLONG)malloc(sizeof(LONG) * 2);
    pData2 = pData1 + 1;

    CreateThread(NULL, 0, Thread1, NULL, 0, &Tid);
    CreateThread(NULL, 0, Thread2, NULL, 0, &Tid);

    system("pause");
    return 0;
}

  这里,两个变量被分配在了一起,可以肯定的是他们会处在同一个CacheLine中,这样两个线程对他们的操作将会产生伪共享。运行结果显示,这种代码运行的时间和上篇中第一个代码,既对同一个变量进行原子操作,需要的时间相近。所以伪共享问题会严重的影响程序的运行性能。
  那么如何避免伪共享呢:
  首先可以对多线程访问的变量按缓存行大小进行内存分配,这种做法固然会浪费一点内存空间,但可以避免伪共享的问题,不同的CPU对不同变量的操作将不会触发缓存同步。
  其次也可以进行读写分离,如果一个结构中部分字段只会对其进行读操作,那么这些可以分配在一起,他们不会产生伪共享,而将写数据单独分配。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值