为什么在多线程程序的不同运行中执行周期的测量是如此不同?

时间:2013-11-12 22:06:33

标签: c linux pthreads arm performance

我解决了模拟制造单元产品的并发问题。我使用了13个未命名的信号量,这些信号量由运行问题“部分”的8个线程处理。

执行周期测量“t1”在phtread_create之后执行,而“t2”在pthread_join之后执行,从而得到pthreads的工作时间(这是我感兴趣的值)。减去t2 -t1给出了结束的线程的执行时间。

我注意到获得的值范围太宽,我测得的值接近30,000个周期。价值1.46亿个周期。

为了测量cicles我使用驱动程序“cicle_count”,其中它读取双核处理器ARM Cortex A9的注册表值R15,该寄存器计算执行的指令数。我使用的嵌入式系统是“ZedBoard”:

http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400.1028&Prod=ZEDBOARD

我使用2线程问题进行测量,更简单,并在每次测量之间获得相似的值。

我做错了什么?可以改变每次运行程序之间执行时间的测量吗?

编辑2:编码whit测量双重和单声道。

对于双核执行(run。/ Aplicacion.out):

我创建了两个相同的驱动程序(编写了相同的代码,但设备名称“DEVICE_NAME”除外),但其中一个名为“contador_ciclos1”,另一个名为“contador_ciclos2”(两个驱动程序是否相同?) )

这些驱动程序在每个核心上插入一个脚本:

insmod hpn_driver.ko
-> Taskset 1 insmod contador_ciclos1.ko
-> Taskset 2 insmod contador_ciclos2.ko
 
mknod / dev / hpn_driver c 251 0
-> Mknod / dev/contador_ciclos1 c 250 0
-> Mknod / dev/contador_ciclos2 c 249 0

然后,在应用程序中,我用两个文件描述符打开两个驱动程序,并进行相关的测量,如t2-t1(core1)和t4-t3(core2)。

要进行单核执行,请插入两个驱动程序,但只打开驱动程序并运行任务集1以测量驱动程序“contador_ciclos1”上的时钟周期。并且olny检查t2-t1 cicles。

这是appacion的伪代码:

  int i = 0;
  char buff[24];
  volatile unsigned int tiempo1, tiempo2;
  tiempo1 = 0;
  tiempo2 = 0;
  volatile unsigned int overhead = 0;

 int fd1, fd2 = 0;

 fd1 = open("/dev/contador_ciclos1", O_RDWR | O_NOCTTY | O_NONBLOCK);
 fd2 = open("/dev/contador_ciclos2", O_RDWR | O_NOCTTY | O_NONBLOCK);


    iret1 = pthread_create( &thread1, NULL     , hilo1_funcion, (void*) mensaje1);
        if (iret1!=0){
        printf("Fallo en creacion hilo 1 %d\n", iret1);
        }

    //create 8 Pthreads...
    //measurement "t1" from core 1 and "t3" from core 2:

  for(i=0;i<10;i++){
  read (fd1,buff,11);
  sscanf(buff,"%u",&tiempo1);
  }

  for(i=0;i<10;i++){
  read (fd2,buff,11);
  sscanf(buff,"%u",&tiempo3);
  }

  pthread_join( thread1, NULL);
  pthread_join( thread2, NULL);

  //measurement "t2" from core 1 and t4 from core 2:

  read (fd1,buff,11);
  sscanf(buff,"%u",&tiempo2);
  read (fd2,buff,11);
  sscanf(buff,"%u",&tiempo4);

  printf(COLOR_VERDE"Ciclos_ejecucion_core1: %u"COLOR_RESET "\n", (tiempo2 - tiempo1));
  printf(COLOR_VERDE"Ciclos_ejecucion_core2: %u"COLOR_RESET "\n", (tiempo4 - tiempo3));

这是使用信号量的“phtread 1”代码......

void *hilo1_funcion( void *ptr ){

    //~ printf(COLOR_MAGENTA"HILO 1"COLOR_RESET"\n");   

    int fabricados3=0; 
    int rc=0;   

    /* Mientras que no se hayan finalizado de fabricar todos los productos 3,
     *  el robot 1 funciona */
    while (fabricados3<productos3){

            rc = sem_trywait(&P3M3);

                     if (rc==-1 && errno == EAGAIN) {    /* no teller available */

                        //~ printf("ROBOT 1 semaforo P3M3 ocupado"COLOR_RESET"\n");      

                     }

           if (rc==0){
                fabricados3++;
                //~ printf(COLOR_CYAN"          PRODUCTO TIPO 3 FINALIZADO - Cantidad de productos tipo 3 fabricados: %d"COLOR_RESET"\n", fabricados3);
                sem_post(&P3R1);
             }  


    //~ printf("YIELD ROBOT 1\n");
    pthread_yield();

    }

    printf(COLOR_ROJO"FIN ROBOT 1"COLOR_RESET"\n");         

    pthread_exit(NULL);
    return NULL;
}

这是驱动程序“contador_ciclos1.ko”的伪代码,在contador_ciclos2.ko也是如此 (

static inline void init_perfcounters (int do_reset, int enable_divider)
{
  // in general enable all counters (including cycle counter)
  static int value = 1;

  // peform reset:
  if (do_reset)
  {
    value |= 2;     // reset all counters to zero.
    value |= 4;     // reset cycle counter to zero.
  }

  if (enable_divider)
    value |= 8;     // enable "by 64" divider for CCNT.

  value |= 16;

  // program the performance-counter control-register:
  asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n" :: "r"(value));

  // enable all counters:
  asm volatile ("MCR p15, 0, %0, c9, c12, 1\t\n" :: "r"(0x8000000f));

  // clear overflows:
  asm volatile ("MCR p15, 0, %0, c9, c12, 3\t\n" :: "r"(0x8000000f));
}
static inline unsigned int get_cyclecount (void)
{
  volatile unsigned int value;
  asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
  return value;
}


int init_module(void)
{
    init_perfcounters(1,0);
    Major = register_chrdev(0, DEVICE_NAME, &fops);
}

static ssize_t device_read(struct file *filp,   
               char *buffer,    
               size_t length,
               loff_t * offset)
{

        volatile unsigned int counter;
        long bytes_read;
        char msg[BUF_LEN];

        counter = get_cyclecount();

        sprintf(msg, "%u", counter);
        bytes_read = copy_to_user(buffer,msg,12);
        if (bytes_read) printk(KERN_ALERT "error en contador.\n");
        return bytes_read;

}

0 个答案:

没有答案