เวลาดำเนินการของโปรแกรม C


209

ฉันมีโปรแกรม C ที่มีวัตถุประสงค์เพื่อให้ทำงานแบบขนานกับโปรเซสเซอร์หลายตัว ฉันต้องสามารถบันทึกเวลาดำเนินการ (ซึ่งอาจเป็นที่ใดก็ได้จาก 1 วินาทีถึงหลายนาที) ฉันค้นหาคำตอบแล้ว แต่พวกเขาดูเหมือนจะแนะนำให้ใช้clock()ฟังก์ชันซึ่งเกี่ยวข้องกับการคำนวณจำนวนนาฬิกาที่โปรแกรมใช้หารด้วยClocks_per_secondค่า

ฉันไม่แน่ใจว่าClocks_per_secondคำนวณค่าได้อย่างไร?

ใน Java ฉันใช้เวลาปัจจุบันเป็นมิลลิวินาทีก่อนและหลังการทำงาน

มีสิ่งที่คล้ายกันใน C? ฉันดูแล้ว แต่ฉันไม่สามารถหาวิธีที่จะได้อะไรที่ดีไปกว่าความละเอียดที่สอง

ฉันยังรู้ว่า profiler จะเป็นตัวเลือก แต่ฉันต้องการใช้ตัวจับเวลา

ขอบคุณ


3
คุณใช้ / มีกรอบงาน OS / API ใดอยู่ แค่ธรรมดา C?
typo.pl

4
เป็นโปรแกรมที่ค่อนข้างเล็กเพียงธรรมดา C
Roger

ฉันได้เขียนรายละเอียดเกี่ยวกับการใช้โซลูชันแบบพกพาในคำตอบนี้: stackoverflow.com/questions/361363/ …
Alexander Saprykin

คำตอบ:


344

CLOCKS_PER_SEC<time.h>เป็นค่าคงที่ซึ่งจะมีการประกาศใน ในการรับเวลา CPU ที่ใช้โดยงานภายในแอปพลิเคชัน C ให้ใช้:

clock_t begin = clock();

/* here, do your time-consuming job */

clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;

โปรดทราบว่านี่จะคืนค่าเวลาเป็นชนิดจุดลอย ซึ่งสามารถแม่นยำกว่าหนึ่งวินาที (เช่นคุณวัด 4.52 วินาที) ความแม่นยำขึ้นอยู่กับสถาปัตยกรรม ในระบบที่ทันสมัยคุณจะได้รับ 10ms หรือต่ำกว่าได้ง่าย แต่สำหรับเครื่อง Windows รุ่นเก่า (จากยุค Win98) มันใกล้ถึง 60ms

clock()คือมาตรฐาน C; มันทำงานได้ "ทุกที่" มีฟังก์ชั่นเฉพาะgetrusage()ระบบเช่นระบบ Unix

Java System.currentTimeMillis()ไม่ได้วัดสิ่งเดียวกัน มันเป็น "นาฬิกาแขวนผนัง": มันสามารถช่วยคุณวัดเวลาที่โปรแกรมใช้ในการรัน แต่มันไม่ได้บอกคุณว่าใช้ CPU มากแค่ไหน ในระบบมัลติทาสก์ (เช่นทั้งหมด) ระบบเหล่านี้อาจแตกต่างกันอย่างกว้างขวาง


1
มันให้ผลลัพธ์แบบสุ่มมาก - ฉันได้รับการผสมของตัวเลขขนาดใหญ่ / เล็ก / ลบบนโค้ดชิ้นเดียวกัน GCC 4.7 Linux 3.2 AMD64

3
ใช่: clock()ส่งคืนเวลาในสเกลภายในบางตัวที่เรียกว่า "นาฬิกา" และCLOCKS_PER_SECคือจำนวนนาฬิกาต่อวินาทีดังนั้นหารด้วยCLOCKS_PER_SECผลตอบแทนเป็นวินาที ในรหัสด้านบนค่าเป็นdoubleเพื่อให้คุณสามารถปรับขนาดตามที่จะ
โทมัส Pornin

18
การเตือนครั้งใหญ่: นาฬิกา () คืนค่าจำนวนเวลาที่ระบบปฏิบัติการใช้ในกระบวนการของคุณไม่ใช่เวลาที่ผ่านไปจริง อย่างไรก็ตามนี่เป็นสิ่งที่ดีสำหรับการจับเวลาบล็อกรหัส แต่ไม่ใช่การวัดเวลาที่ผ่านไปในโลกแห่งความจริง

2
เขาบอกว่าเขาต้องการวัดโปรแกรมแบบมัลติเธรด ฉันไม่แน่ใจว่านาฬิกา () เหมาะสำหรับสิ่งนี้เพราะจะสรุปเวลาการทำงานของเธรดทั้งหมดดังนั้นผลลัพธ์จะดูเหมือนว่ารหัสถูกเรียกใช้ตามลำดับ สำหรับสิ่งต่าง ๆ ที่ฉันใช้ omp_get_wtime () แต่แน่นอนฉันต้องแน่ใจว่าระบบไม่ยุ่งกับกระบวนการอื่น
Youda008

1
ฉันควรพูดถึงบางสิ่งแม้ว่าเธรดนี้จะมีความเกี่ยวข้องมากขึ้นเมื่อปีที่แล้ว: CLOCKS_PER_SECเป็นสิ่งที่long intมีค่า1000000โดยให้เวลาเป็นไมโครวินาทีเมื่อไม่แบ่งออก ไม่ใช่รอบสัญญาณนาฬิกาของ CPU ดังนั้นมันไม่จำเป็นที่จะต้องคำนึงถึงความถี่แบบไดนามิกเนื่องจากนาฬิกาที่นี่มีหน่วยเป็นไมโครวินาที (อาจเป็นวงจรสัญญาณนาฬิกาสำหรับ 1 MHz ซีพียู) ฉันทำโปรแกรม C สั้น ๆ พิมพ์ค่านั้นและมันเป็น 1000000 บนแล็ปท็อป i7-2640M ของฉัน ด้วยความถี่แบบไดนามิกที่ช่วยให้ 800 MHz ถึง 2.8 GHz แม้จะใช้ Turbo Boost สูงถึง 3.5 GHz
DDPWNAGE

111

หากคุณใช้เชลล์ Unix สำหรับการเรียกใช้คุณสามารถใช้คำสั่ง time

การทำ

$ time ./a.out

สมมติว่า a.out เป็นไฟล์เรียกทำงานจะให้เวลากับคุณในการรัน


3
@acgtyrant แต่สำหรับโปรแกรมง่ายเพราะมันจะใช้เวลาโปรแกรมรวมทั้งนำเข้าส่งออก ฯลฯ
phuclv

1
หากคุณอยู่บน Linux และคุณได้ลดมาตรฐาน (micro) เป็นโปรแกรมที่มีค่าใช้จ่ายในการเริ่มต้นที่น้อยมากเช่นไฟล์เอ็กซีคิวต์แบบคงที่ที่รัน hot loop ของคุณสักสองสามวินาทีคุณสามารถใช้perf stat ./a.outเพื่อรับเคาน์เตอร์ประสิทธิภาพ HW สำหรับแคช และการคาดคะเนสาขาผิดและ IPC
Peter Cordes

61

ในวานิลลาธรรมดา C:

#include <time.h>
#include <stdio.h>

int main()
{
    clock_t tic = clock();

    my_expensive_function_which_can_spawn_threads();

    clock_t toc = clock();

    printf("Elapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);

    return 0;
}

6
ชื่อตัวแปรที่ดีที่สุดที่ฉันเคยเห็นในชั่วขณะหนึ่ง tic = "นาฬิกาในเวลา", toc = "นาฬิกาหมดเวลา" แต่ยัง tic-toc = "tick-tock" นี่คือวิธีที่ฉันติดป้ายเวลาคว้าจากที่นี่ออกมา
โลแกน Schelly

60

คุณต้องการสิ่งนี้:

#include <sys/time.h>

struct timeval  tv1, tv2;
gettimeofday(&tv1, NULL);
/* stuff to do! */
gettimeofday(&tv2, NULL);

printf ("Total time = %f seconds\n",
         (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 +
         (double) (tv2.tv_sec - tv1.tv_sec));

โปรดทราบว่ามาตรการนี้มีหน่วยเป็นไมโครวินาทีไม่ใช่เพียงแค่วินาที


2
คอมไพเลอร์ MinGW เป็นพื้นฐานของ GCC ดังนั้นมันจะทำงานกับมัน แต่ถ้าคุณใช้คอมไพเลอร์ Visual C คุณจะได้รับข้อผิดพลาด
2550754

11
ใช่มันจะทำงานบน windows ด้วยไลบรารี ac ที่รองรับการโทร gettimeofday มันไม่สำคัญว่าคอมไพเลอร์คืออะไรคุณแค่ต้องเชื่อมโยงมันกับไลบรารี libc ที่เหมาะสม ซึ่งในกรณีของ mingw จะไม่ใช่หน้าต่างเริ่มต้น
Wes Hardaker

1
สิ่งนี้ใช้ได้กับฉันใน Windows XP ด้วย cygwin gcc & Linux Ubuntu นี่คือสิ่งที่ฉันต้องการ
ความรักและความสงบสุข - Joe Codeswell

gettimeofdayล้าสมัยและไม่แนะนำให้ใช้รหัสใหม่ หน้าเว็บ POSIX ของมันแนะนำclock_gettimeแทนซึ่งช่วยให้คุณสามารถขอให้CLOCK_MONOTONICสิ่งนั้นไม่ได้รับผลกระทบจากการเปลี่ยนแปลงนาฬิการะบบและทำให้ดีขึ้นตามช่วงเวลา (ดูคำตอบของ JohnSll ) บนระบบ Linux ที่ทันสมัยตัวอย่างเช่น gettimeofday นั้นเป็น wrapper สำหรับ clock_gettime ซึ่งแปลง nanoseconds เป็น microseconds
Peter Cordes

12

โปรแกรมอย่างง่ายส่วนใหญ่มีเวลาการคำนวณเป็นมิลลิวินาที ดังนั้นฉันคิดว่าคุณจะพบว่ามีประโยชน์นี้

#include <time.h>
#include <stdio.h>

int main(){
    clock_t start = clock();
    // Execuatable code
    clock_t stop = clock();
    double elapsed = (double)(stop - start) * 1000.0 / CLOCKS_PER_SEC;
    printf("Time elapsed in ms: %f", elapsed);
}

หากคุณต้องการคำนวณรันไทม์ของโปรแกรมทั้งหมดและคุณอยู่ในระบบ Unix ให้รันโปรแกรมของคุณโดยใช้คำสั่งtimeเช่นนี้time ./a.out


ใน Windows อย่างน้อยที่สุดปัจจัยคืออย่างน้อย 100 แต่ไม่ใช่ 1,000 และไม่แน่นอน
boctulus

6
คำตอบนี้ไม่ได้เพิ่มอะไรที่ไม่ได้อยู่ในคำตอบของAlexandre Cจากสองปีก่อน
Jonathan Leffler

3
@boctulus: 1s อยู่เสมอ 1,000 มิลลิวินาทีเช่นกันบน windows
alk

9

มีคำตอบมากมายที่แนะนำclock()และCLOCKS_PER_SECจากtime.hนั้น นี่อาจเป็นความคิดที่ไม่ดีเพราะนี่คือสิ่งที่/bits/time.hไฟล์ของฉันพูด:

/* ISO/IEC 9899:1990 7.12.1: <time.h>
The macro `CLOCKS_PER_SEC' is the number per second of the value
returned by the `clock' function. */
/* CAE XSH, Issue 4, Version 2: <time.h>
The value of CLOCKS_PER_SEC is required to be 1 million on all
XSI-conformant systems. */
#  define CLOCKS_PER_SEC  1000000l

#  if !defined __STRICT_ANSI__ && !defined __USE_XOPEN2K
/* Even though CLOCKS_PER_SEC has such a strange value CLK_TCK
presents the real value for clock ticks per second for the system.  */
#   include <bits/types.h>
extern long int __sysconf (int);
#   define CLK_TCK ((__clock_t) __sysconf (2))  /* 2 is _SC_CLK_TCK */
#  endif

ดังนั้นCLOCKS_PER_SECอาจถูกกำหนดเป็น 1000000 ขึ้นอยู่กับตัวเลือกที่คุณใช้ในการรวบรวมและดังนั้นจึงดูเหมือนจะไม่เป็นทางออกที่ดี


1
ขอบคุณสำหรับข้อมูล แต่มีทางเลือกที่ดีกว่านี้หรือยัง
ozanmuyes

4
นี่ไม่ใช่ปัญหาที่เกิดขึ้นจริง: ใช่ระบบของ Posix มักจะมีCLOCK_PER_SEC==1000000แต่ในเวลาเดียวกันพวกมันก็ใช้ความแม่นยำ 1- ในการปรับใช้นาฬิกา () โดยวิธีการที่มันมีคุณสมบัติที่ดีในการลดปัญหาการแบ่งปัน หากคุณต้องการวัดเหตุการณ์ที่อาจเกิดขึ้นอย่างรวดเร็วให้พูดต่ำกว่า 1 ms ก่อนอื่นคุณควรกังวลเกี่ยวกับความถูกต้อง (หรือความละเอียด) ของฟังก์ชั่น clock () ซึ่งจำเป็นต้องมีความหยาบมากกว่า 1 ใน Posix แต่ก็มักจะหยาบกว่ามาก วิธีการแก้ปัญหาตามปกติคือการเรียกใช้การทดสอบหลายครั้ง แม้ว่าคำถามที่ถามมาดูเหมือนจะไม่ต้องการก็ตาม
AntoineL

ทำไมมันไม่เป็นทางออกที่ดี? คุณจะได้รับค่าบางอย่างจากclock()ถ้าคุณแบ่งค่านั้นกับCLOCK_PER_SECคุณรับประกันว่าจะได้เวลาในไม่กี่วินาที cpu เอา ความรับผิดชอบในการวัดความเร็วสัญญาณนาฬิกาจริงเป็นความรับผิดชอบของclock()ฟังก์ชั่นไม่ใช่ของคุณ
Zaffy

9

คำตอบของ Thomas Pornin ในฐานะมาโคร:

#define TICK(X) clock_t X = clock()
#define TOCK(X) printf("time %s: %g sec.\n", (#X), (double)(clock() - (X)) / CLOCKS_PER_SEC)

ใช้แบบนี้:

TICK(TIME_A);
functionA();
TOCK(TIME_A);

TICK(TIME_B);
functionB();
TOCK(TIME_B);

เอาท์พุท:

time TIME_A: 0.001652 sec.
time TIME_B: 0.004028 sec.

4

คุณต้องคำนึงถึงว่าการวัดเวลาที่ใช้ในการรันโปรแกรมนั้นขึ้นอยู่กับภาระที่เครื่องมีในช่วงเวลานั้น

รู้ว่าวิธีการรับเวลาปัจจุบันใน C สามารถทำได้ในรูปแบบที่แตกต่างกันวิธีที่ง่ายกว่าคือ:

#include <time.h>

#define CPU_TIME (getrusage(RUSAGE_SELF,&ruse), ruse.ru_utime.tv_sec + \
  ruse.ru_stime.tv_sec + 1e-6 * \
  (ruse.ru_utime.tv_usec + ruse.ru_stime.tv_usec))

int main(void) {
    time_t start, end;
    double first, second;

    // Save user and CPU start time
    time(&start);
    first = CPU_TIME;

    // Perform operations
    ...

    // Save end time
    time(&end);
    second = CPU_TIME;

    printf("cpu  : %.2f secs\n", second - first); 
    printf("user : %d secs\n", (int)(end - start));
}

หวังว่ามันจะช่วย

ความนับถือ!


4

(คำตอบทั้งหมดที่นี่ขาดหากดูแลระบบของคุณเปลี่ยน systemtime หรือเขตเวลาของคุณมีฤดูหนาวและซัมเมอร์ต่างกันดังนั้น ... )

เกี่ยวกับการใช้งาน linux: clock_gettime(CLOCK_MONOTONIC_RAW, &time_variable); จะไม่ได้รับผลกระทบหากผู้ดูแลระบบเปลี่ยนเวลาหรือคุณอาศัยอยู่ในประเทศที่มีเวลาฤดูหนาวแตกต่างจากฤดูร้อนเป็นต้น

#include <stdio.h>
#include <time.h>

#include <unistd.h> /* for sleep() */

int main() {
    struct timespec begin, end;
    clock_gettime(CLOCK_MONOTONIC_RAW, &begin);

    sleep(1);      // waste some time

    clock_gettime(CLOCK_MONOTONIC_RAW, &end);

    printf ("Total time = %f seconds\n",
            (end.tv_nsec - begin.tv_nsec) / 1000000000.0 +
            (end.tv_sec  - begin.tv_sec));

}

man clock_gettime รัฐ:

CLOCK_MONOTONIC
              Clock  that  cannot  be set and represents monotonic time since some unspecified starting point.  This clock is not affected by discontinuous jumps in the system time
              (e.g., if the system administrator manually changes the clock), but is affected by the incremental adjustments performed by adjtime(3) and NTP.

คุณสามารถอธิบายการคำนวณที่คุณใช้เพื่อรับจำนวนวินาทีได้หรือไม่ ไม่ชัดเจนว่าเกิดอะไรขึ้น
โคลินคีแนนส์มี. ค.

1
สิ่งนี้จะไม่(end.tv_nsec - begin.tv_nsec) / 1000000000.0ส่งผล0เสมอหรือไม่
alk

@alk: ไม่หารด้วยdoubleตัวอักษรทริกเกอร์ int หรือlongการdoubleแปลงก่อนการหาร แน่นอนว่าคุณสามารถเกาะติดจำนวนเต็มแล้วพิมพ์tv_secส่วนแล้วเศษส่วนที่มีศูนย์เหมือน%ld.%09ldกัน แต่การแปลงให้เป็นสองเท่านั้นง่ายและ 53 บิตของความแม่นยำมักจะเพียงพอสำหรับเวลามาตรฐาน
Peter Cordes

1
(โอ๊ะการลบส่วน nanoseconds อาจต้องดำเนินการในส่วนวินาทีดังนั้นการใช้สองครั้งและปล่อยให้เป็นเชิงลบเพื่อหลีกเลี่ยงปัญหานั้นในการใช้สตริงรูปแบบจำนวนเต็มแท้คุณจะต้องมีtimespec_subtractคำtimeval_subtractแนะนำในคู่มือ glibc : gnu.org/software/libc/manual/html_node/Elapsed-Time.html )
Peter Cordes

3

ANSI C ระบุฟังก์ชันเวลาความแม่นยำที่สองเท่านั้น อย่างไรก็ตามหากคุณกำลังทำงานในสภาพแวดล้อม POSIX คุณสามารถใช้ฟังก์ชันgettimeofday ()ที่ให้เวลาในการแก้ปัญหาไมโครวินาทีได้ตั้งแต่ UNIX Epoch

ในฐานะที่เป็นหมายเหตุด้านข้างฉันไม่แนะนำให้ใช้ clock () เนื่องจากมีการใช้งานอย่างไม่ถูกต้องในระบบหลายระบบ (ถ้าไม่ใช่ทั้งหมด) และไม่ถูกต้องนอกจากความจริงที่ว่ามันอ้างถึงระยะเวลาที่โปรแกรมของคุณใช้ CPU ไม่ใช่อายุการใช้งานทั้งหมดของโปรแกรมซึ่งตามคำถามของคุณคือสิ่งที่ฉันคิดว่าคุณต้องการวัด


ISO C มาตรฐาน (สมมติว่านี่คือสิ่งที่ANSI Cหมายถึง) จงใจไม่ได้ระบุความแม่นยำของฟังก์ชั่นเวลา จากนั้นในการใช้งาน POSIX โดยเฉพาะหรือบน Windows ความแม่นยำของฟังก์ชั่นนาฬิกาแขวน (ดูคำตอบของโทมัส) จะใช้เวลาไม่กี่วินาที แต่ความแม่นยำของ clock () มักจะมากกว่าและ 1 ands ใน Posix เสมอ (ไม่ขึ้นกับความถูกต้อง)
AntoineL

2

ทุกโซลูชันไม่ทำงานในระบบของฉัน

ฉันสามารถใช้

#include <time.h>

double difftime(time_t time1, time_t time0);

2
สิ่งนี้ให้ความแตกต่างระหว่างสองtime_tค่าเป็นสองเท่า เนื่องจากtime_tค่านั้นมีความแม่นยำเพียงเสี้ยววินาทีมันจึงมีค่า จำกัด ในการพิมพ์เวลาที่ใช้โดยโปรแกรมที่รันในระยะสั้นถึงแม้ว่ามันอาจจะมีประโยชน์สำหรับโปรแกรมที่รันเป็นเวลานาน
Jonathan Leffler

ไม่ว่าด้วยเหตุผลใดก็ตามการส่งผ่านคู่หนึ่งclock_tไปdifftimeดูเหมือนว่าจะทำงานให้ฉันเพื่อความแม่นยำของหนึ่งร้อยวินาที นี่คือบน linux x86 ฉันไม่สามารถลบstopและstartทำงานได้
ragerdl

@ragerdl: คุณต้องผ่านไปdifftime() clock() / CLOCKS_PER_SECตามที่คาดไว้วินาที
alk

2
    #include<time.h>
    #include<stdio.h>
    int main(){
clock_t begin=clock();

    int i;
for(i=0;i<100000;i++){
printf("%d",i);

}
clock_t end=clock();
printf("Time taken:%lf",(double)(end-begin)/CLOCKS_PER_SEC);
}

โปรแกรมนี้จะทำงานเหมือนมีเสน่ห์


2

ฉันพบว่านาฬิกาปกติ () ทุกคนแนะนำที่นี่ด้วยเหตุผลบางอย่างเบี่ยงเบนอย่างรุนแรงจากการทำงานเพื่อเรียกใช้แม้สำหรับรหัสคงที่ไม่มีผลข้างเคียงใด ๆ เช่นการวาดภาพไปที่หน้าจอหรือการอ่านไฟล์ อาจเป็นเพราะ CPU เปลี่ยนโหมดการใช้พลังงานระบบปฏิบัติการที่ให้ความสำคัญต่างกัน ฯลฯ

ดังนั้นวิธีเดียวที่จะได้ผลลัพธ์เดียวกันอย่างน่าเชื่อถือทุกครั้งที่มีนาฬิกา () คือการเรียกใช้โค้ดที่วัดได้ในลูปหลาย ๆ ครั้ง (เป็นเวลาหลายนาที) การระมัดระวังเพื่อป้องกันคอมไพเลอร์จากการปรับมันออก: คอมไพเลอร์สมัยใหม่ ไม่มีผลข้างเคียงที่ทำงานในลูปและย้ายออกจากลูปเช่นใช้การสุ่มอินพุตสำหรับการวนซ้ำแต่ละครั้ง

หลังจากเก็บตัวอย่างเพียงพอไปยังอาร์เรย์หนึ่งประเภทนั้นจะเรียงลำดับและใช้องค์ประกอบกลางเรียกว่ามัธยฐาน ค่ามัธยฐานนั้นดีกว่าค่าเฉลี่ยเพราะมันเบี่ยงเบนความเบี่ยงเบนอย่างสุดขั้วออกไปเช่นบอกว่าการป้องกันไวรัสทำให้ CPU ทั้งหมดหรือระบบปฏิบัติการทำการอัพเดท

นี่คือยูทิลิตี้ง่าย ๆ ในการวัดประสิทธิภาพการทำงานของรหัส C / C ++ โดยเฉลี่ยค่าใกล้กับค่ามัธยฐาน: https://github.com/saniv/gauge

ฉันเองยังคงมองหาวิธีที่แข็งแกร่งและเร็วกว่าในการวัดโค้ด หนึ่งอาจลองใช้รหัสในสภาพควบคุมบนโลหะเปลือยโดยไม่มีระบบปฏิบัติการใด ๆ แต่ที่จะให้ผลลัพธ์ที่ไม่สมจริงเพราะในความเป็นจริงระบบปฏิบัติการจะมีส่วนร่วม

x86 มีตัวนับประสิทธิภาพของฮาร์ดแวร์เหล่านี้ซึ่งรวมถึงจำนวนคำสั่งที่เรียกใช้จริง แต่ทำได้ยากหากต้องการเข้าถึงโดยไม่ต้องใช้ระบบปฏิบัติการช่วยเหลือยากที่จะตีความและมีปัญหาของตัวเอง ( http://archive.gamedev.net/archive/reference/articles/articles) /article213.html ) ถึงกระนั้นก็อาจเป็นประโยชน์ในการตรวจสอบลักษณะของคอขวด (การเข้าถึงข้อมูลหรือการคำนวณจริงในข้อมูลนั้น)


ใช่ซีพียู x86 รุ่นใหม่ใช้งานช้ากว่าเทอร์โบสูงสุดมาก ทั้งนี้ขึ้นอยู่กับการตั้งค่า "ผู้ว่าราชการ" ความเร็วสูงถึงสูงสุดของนาฬิกาอาจใช้เวลามิลลิวินาที (Skylake พร้อมการจัดการ P-state ของฮาร์ดแวร์โดยเฉพาะอย่างยิ่งกับ energy_performance_preference ตั้งค่าเป็นperformance) หรือหลายสิบมิลลิวินาที en.wikipedia.org/wiki/Dynamic_frequency_scaling และใช่แล้วค่ามัธยฐานมักเป็นตัวเลือกที่ดี ปลายสูงมักจะมีหนามแหลมบางอย่างจากการรบกวน
Peter Cordes

บ่อยครั้งทางออกที่ดีที่สุดของคุณเพื่อหลีกเลี่ยงการเพิ่มประสิทธิภาพการทำงานคือการป้อนบรรทัดคำสั่งและส่งคืนผลลัพธ์ หรือเขียนฟังก์ชั่นในไฟล์แยกต่างหากจากmainนั้นจะหาเรื่องและส่งคืนผลลัพธ์และไม่ใช้การปรับเวลาลิงก์ให้เหมาะสม จากนั้นคอมไพเลอร์ไม่สามารถแทรกเข้าไปในผู้โทร ใช้งานได้เฉพาะเมื่อฟังก์ชันมีลูปบางประเภทอยู่แล้วมิฉะนั้นค่าโทร / ret จะสูงเกินไป
Peter Cordes

คอมไพเลอร์ยังคงสามารถเพิ่มประสิทธิภาพบรรทัดคำสั่งเดียวออกจากลูปถ้าคุณประมวลผลด้วยรหัสคงที่โดยไม่มีผลข้างเคียงใด ๆ ดังนั้นจึงควรสร้างอินพุตสุ่มสำหรับการวนซ้ำแต่ละครั้ง เห็นได้ชัดว่า rand () ควรถูกเรียกใช้นอกรหัสที่วัดได้ก่อนนาฬิกาแรก () เพราะ rand () อาจส่งผลให้เกิดการเรียกของระบบรวมถึงการสุ่มตัวอย่างเอนโทรปีของฮาร์ดแวร์ (ซึ่งในระบบเก่าคือการเคลื่อนที่ของเมาส์) อย่าลืมพิมพ์เอาท์พุททุก ๆ อย่างไม่เช่นนั้นคอมไพเลอร์อาจตัดสินใจว่าคุณไม่จำเป็นต้องใช้เอาท์พุตทั้งหมดหรือบางส่วน สามารถทำได้ด้วยการพูด CRC32
SmugLispWeenie

หากรหัสของคุณภายใต้การทดสอบในไฟล์แยกต่างหากและคุณไม่ได้ใช้การเพิ่มประสิทธิภาพลิงค์เวลาไม่มีวิธีที่คอมไพเลอร์สามารถทำ CSE เพื่อเพิ่มประสิทธิภาพระหว่างการโทร ผู้เรียกไม่สามารถคิดอะไรเกี่ยวกับผู้ที่ไม่มีผู้เห็นผลข้างเคียงใด ๆ สิ่งนี้ช่วยให้คุณวางบางสิ่งบางอย่างที่ค่อนข้างสั้นในลูปการวนซ้ำเพื่อให้นานพอเพียงด้วยการโทร / ret โอเวอร์เฮด หากคุณปล่อยให้อินไลน์คุณต้องตรวจสอบ asm ที่สร้างขึ้นเพื่อให้แน่ใจว่ามันไม่ได้ยกการคำนวณออกจากลูปตามที่คุณพูด
Peter Cordes

วิธีเฉพาะของคอมไพเลอร์คือการใช้ (ตัวอย่าง) GNU C inline asm เพื่อบังคับให้คอมไพเลอร์สร้างผลลัพธ์ในรีจิสเตอร์และ / หรือลืมสิ่งที่รู้เกี่ยวกับคุณค่าของตัวแปรโดยไม่แนะนำวิธีการพิเศษจริง ๆ "Escape" และ "Clobber" ในลิงก์MSVCไปยังวิดีโอเกี่ยวกับการทำโปรไฟล์และการทำเครื่องหมายขนาดเล็ก (การพูดคุย CppCon 2015 ของผู้พัฒนาเสียงดัง Chandler Carruth ในการพูดคุย) ไม่มีอะไรเทียบเท่า MSVC แต่คำถามแสดงให้เห็นถึงฟังก์ชัน GNU C และวิธีการใช้งาน
Peter Cordes

0

บางคนอาจพบว่าการป้อนข้อมูลประเภทอื่นมีประโยชน์: ฉันได้รับวิธีการวัดเวลานี้เป็นส่วนหนึ่งของหลักสูตรมหาวิทยาลัยในการเขียนโปรแกรม GPGPU กับ NVidia CUDA ( คำอธิบายหลักสูตร ) มันรวมวิธีการที่เห็นในโพสต์ก่อนหน้านี้และฉันโพสต์เพียงเพราะข้อกำหนดให้ความน่าเชื่อถือ:

unsigned long int elapsed;
struct timeval t_start, t_end, t_diff;
gettimeofday(&t_start, NULL);

// perform computations ...

gettimeofday(&t_end, NULL);
timeval_subtract(&t_diff, &t_end, &t_start);
elapsed = (t_diff.tv_sec*1e6 + t_diff.tv_usec);
printf("GPU version runs in: %lu microsecs\n", elapsed);

ฉันคิดว่าคุณสามารถคูณด้วยเช่น1.0 / 1000.0เพื่อให้ได้หน่วยการวัดที่ตรงกับความต้องการของคุณ


1
gettimeofday ล้าสมัยและไม่แนะนำ หน้าคู่มือPOSIX แนะนำให้clock_gettimeใช้แทนซึ่งจะช่วยให้คุณสามารถถามCLOCK_MONOTONICได้ว่าไม่ได้รับผลกระทบใด ๆ จากการเปลี่ยนแปลงของนาฬิการะบบ ยกตัวอย่างเช่นระบบลีนุกซ์สมัยใหม่gettimeofdayนั้นเป็นตัวหุ้มสำหรับclock_gettimeแปลงนาโนวินาทีเป็นไมโครวินาที (ดูคำตอบของ JohnSll)
Peter Cordes

วิธีการนี้ถูกบันทึกโดย @Wes Hardaker timeval_subtractแตกต่างที่สำคัญคือการใช้
ワイきんぐ

ตกลงดังนั้นส่วนที่มีประโยชน์ของคำตอบของคุณคือชื่อของฟังก์ชันที่คุณไม่ได้กำหนดและไม่ได้อยู่ในไลบรารีมาตรฐาน (เฉพาะในคู่มือ glibc: gnu.org/software/libc/manual/html_node/Elapsed-Time.html )
Peter Cordes

-2

การเปรียบเทียบเวลาดำเนินการของการจัดเรียงฟองและการจัดเรียงการเลือกฉันมีโปรแกรมที่เปรียบเทียบเวลาดำเนินการของการจัดเรียงฟองและการจัดเรียงการเลือก เพื่อหาเวลาในการประมวลผลบล็อกของรหัสคำนวณเวลาก่อนและหลังบล็อกโดย

 clock_t start=clock();
 
 clock_t end=clock();
 CLOCKS_PER_SEC is constant in time.h library

รหัสตัวอย่าง:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
   int a[10000],i,j,min,temp;
   for(i=0;i<10000;i++)
   {
      a[i]=rand()%10000;
   }
   //The bubble Sort
   clock_t start,end;
   start=clock();
   for(i=0;i<10000;i++)
   {
     for(j=i+1;j<10000;j++)
     {
       if(a[i]>a[j])
       {
         int temp=a[i];
         a[i]=a[j];
         a[j]=temp;
       }
     }
   }
   end=clock();
   double extime=(double) (end-start)/CLOCKS_PER_SEC;
   printf("\n\tExecution time for the bubble sort is %f seconds\n ",extime);

   for(i=0;i<10000;i++)
   {
     a[i]=rand()%10000;
   }
   clock_t start1,end1;
   start1=clock();
   // The Selection Sort
   for(i=0;i<10000;i++)
   {
     min=i;
     for(j=i+1;j<10000;j++)
     {
       if(a[min]>a[j])
       {
         min=j;
       }
     }
     temp=a[min];
     a[min]=a[i];
     a[i]=temp;
   }
   end1=clock();
   double extime1=(double) (end1-start1)/CLOCKS_PER_SEC;
   printf("\n");
   printf("\tExecution time for the selection sort is %f seconds\n\n", extime1);
   if(extime1<extime)
     printf("\tSelection sort is faster than Bubble sort by %f seconds\n\n", extime - extime1);
   else if(extime1>extime)
     printf("\tBubble sort is faster than Selection sort by %f seconds\n\n", extime1 - extime);
   else
     printf("\tBoth algorithms have the same execution time\n\n");
}

4
สิ่งนี้ไม่ได้เพิ่มอะไรใหม่เปรียบเทียบกับคำตอบของadimohยกเว้นว่ามันจะเติมเต็มในบล็อก 'รหัสที่สามารถใช้งานได้' (หรือสองรายการ) ด้วยรหัสจริงบางอย่าง และคำตอบนั้นไม่ได้เพิ่มอะไรที่ไม่ได้อยู่ในคำตอบของAlexandre Cจากสองปีก่อน
Jonathan Leffler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.