lunixwh 发表于 2016-07-13 15:05

请大神指导为什么这两个结构体的性能不一样,关于cache

下面两个结构体性能不一样

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>

#ifndef __aligned
#define __aligned(x)                        __attribute__((aligned(x)))
#endif

#define cache_line_size 64

这两个结构体性能不一样
struct buf{
        char buf1;
        char buf2;
        char buf;
        char buf3;
};

struct buf_align{
        char buf1;
        char buf2;
        char buf;
        char buf3;
};

struct buf data;
struct buf_align data_align;

#define time 100000000

void thread(void *cpu)
{
        int i = 0;
        struct timeval tv_begin, tv_end;

        cpu_set_t mask;
        CPU_ZERO(&mask);
        int tmp_cpu = *(int *)cpu;
        CPU_SET(tmp_cpu, &mask);
        if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
                printf("set thread affinity failed\n");

        }

        cpu_set_t get;
        CPU_ZERO(&get);
        if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
                printf("get thread affinity failed\n");
        }else{
                int j;
                for(j = 0; j < 4; j++){
                        if(CPU_ISSET(j, &get)) {
                                printf("thread%d is core%d\n",*(int *)cpu, j);
                        }
                }
        }
       
        gettimeofday(&tv_begin, NULL);
        for(i = 0; i < time; i++){               
                        strncpy((data.buf1),"01234567890123456789",20);
                        memset(&(data.buf1), 0, 20);               
                        strncpy((data.buf2),"01234567890123456789",20);
                        memset(&(data.buf2), 0, 20);               
        }
        gettimeofday(&tv_end, NULL);
        printf("time:%d\n", (tv_end.tv_sec - tv_begin.tv_sec)*1000000 + (tv_end.tv_usec - tv_begin.tv_usec));
       
        /*align*/
        gettimeofday(&tv_begin, NULL);
        for(i = 0; i < time; i++){               
                        strncpy((data_align.buf1),"01234567890123456789",20);
                        memset(&(data_align.buf1), 0, 20);               
                        strncpy((data_align.buf2),"01234567890123456789",20);
                        memset(&(data_align.buf2), 0, 20);               
        }
        gettimeofday(&tv_end, NULL);
        printf("align time:%d\n", (tv_end.tv_sec - tv_begin.tv_sec)*1000000 + (tv_end.tv_usec - tv_begin.tv_usec));

}

int cpu_num = 1;

int main(void)
{

        pthread_t tid;
        int tmp;
        int i,ret;

        memset(&data, 0, sizeof(struct buf)*3);
        printf("size %d, align_size:%d\n",sizeof(struct buf),sizeof(struct buf_align));

        for(i = 0; i < cpu_num; i++){
                tmp = i;
                ret=pthread_create(&tid,NULL,(void *) thread, &tmp);
                if(ret!=0){
                        printf ("Create pthread error!\n");
                        return 1;
                }
        }

        for(i = 0; i < cpu_num; ++i)
        {
                pthread_join(tid,NULL);
        }

        return 0;
}
编译 gcc wlong.c -lpthread -o no
$ ./no
size 252, align_size:316
thread0 is core0
time:672585
align time:620361

实际上两个结构体只用到了上面的buf1 和buf2 为什么后面的长度会对性能有影响?请大神指导!!!

hellioncu 发表于 2016-07-13 16:09

你这点估计是误差。跨多个cache line性能会慢,你只有一个线程,只用了最前面40字节,不存在此问题

lunixwh 发表于 2016-07-13 16:13

回复 2# hellioncu


    这个我试了很多次,如果字节对齐的话时间就会反过来,用时长的时间反而短,用时短的结构时间反而长。程序都在上面了,你也可以试试

lunixwh 发表于 2016-07-13 16:13

回复 2# hellioncu


    这个我试了很多次,如果字节对齐的话时间就会反过来,用时长的时间反而短,用时短的结构时间反而长。程序都在上面了,你也可以试试

hellioncu 发表于 2016-07-13 16:21

lunixwh 发表于 2016-07-13 16:13 static/image/common/back.gif
回复 2# hellioncu




你把
struct buf data;
struct buf_align data_align;

的先后次序换一下试试

lunixwh 发表于 2016-07-13 16:35

回复 5# hellioncu


    $ ./a.out
size 92, align_size:88
thread0 is core0
time:1328583
align time:1657367

$ ./a.out               
size 92, align_size:88
thread0 is core0
align time:1909747
time:1473750

换了一下顺序,是线程中的执行顺序

nswcfd 发表于 2016-07-13 17:00

本帖最后由 nswcfd 于 2016-07-13 18:08 编辑

测试了一下,调换数据的先后顺序没有影响,但是调换访问的顺序(先test align后test 非align)时间就交换了一下(先做的快,后做的慢),或者中间加入sleep(1)有时候也能把时间拉平.

或者先把数据warm一下(即插入几个memset),也能把两者的差异拉平。

PS,sleep的效果很诡异…… 难道是能等待未完成的cache同步结束?

PS2,这个效果跟buf无关,如果两个结构都只有40字节,效果没有变化。

PS3,把两个结构都对齐到64/128字节也不改变效果。

nswcfd 发表于 2016-07-13 18:08

本帖最后由 nswcfd 于 2016-07-13 20:23 编辑

有可能是gettimeofday或者printf的副作用?换成rdtscll并去掉打印,结果就一致了,先调用的时间长,后调用的时间短。

同样,预热一下数据,两者的差距就很小了。
页: [1]
查看完整版本: 请大神指导为什么这两个结构体的性能不一样,关于cache