மோசமான சோதனை பற்றி இன்னும் கொஞ்சம்

ஒரு நாள் தற்செயலாக ஒரு பயனர் தனது மெய்நிகர் கணினியில் ரேம் செயல்திறனைக் கண்காணிக்க முயற்சிக்கும் குறியீட்டைக் கண்டேன். நான் இந்த குறியீட்டை கொடுக்க மாட்டேன் (அங்கு ஒரு "கால் துணி" உள்ளது) மற்றும் நான் மிகவும் அத்தியாவசியமானவற்றை மட்டும் விட்டுவிடுகிறேன். எனவே, பூனை ஸ்டுடியோவில் உள்ளது!

#include <sys/time.h>
#include <string.h>
#include <iostream>

#define CNT 1024
#define SIZE (1024*1024)

int main() {
	struct timeval start;
	struct timeval end;
	long millis;
	double gbs;
	char ** buffers;
	buffers = new char*[CNT];
	for (int i=0;i<CNT;i++) {
		buffers[i] = new char[SIZE];
	}
	gettimeofday(&start, NULL);
	for (int i=0;i<CNT;i++) {
		memset(buffers[i], 0, SIZE);
	}
	gettimeofday(&end, NULL);
	millis = (end.tv_sec - start.tv_sec) * 1000 +
		(end.tv_usec - start.tv_usec) / 1000;
	gbs = 1000.0 / millis;
	std::cout << gbs << " GB/sn";
	for (int i=0;i<CNT;i++) {
		delete buffers[i];
	}
	delete buffers;
	return 0;
}

இது எளிது - நினைவகத்தை ஒதுக்கி அதில் ஒரு ஜிகாபைட் எழுதவும். இந்த சோதனை என்ன காட்டுகிறது?

$ ./memtest
4.06504 GB / s

தோராயமாக 4GB/s.

என்ன?!?!

எப்படி?!?!?

இது கோர் i7 (புதியதாக இல்லாவிட்டாலும்), DDR4, செயலி கிட்டத்தட்ட ஏற்றப்படவில்லை - ஏன்?!?!

பதில், எப்போதும் போல, வழக்கத்திற்கு மாறாக சாதாரணமானது.

புதிய ஆபரேட்டர் (malloc செயல்பாடு போன்றது) உண்மையில் நினைவகத்தை ஒதுக்கவில்லை. இந்த அழைப்பின் மூலம், ஒதுக்கீட்டாளர் நினைவகக் குளத்தில் உள்ள இலவச இருப்பிடங்களின் பட்டியலைப் பார்க்கிறார், எதுவும் இல்லை என்றால், தரவுப் பிரிவை அதிகரிக்க sbrk() ஐ அழைக்கிறார், பின்னர் புதிய இடத்திலிருந்து முகவரிக்கான குறிப்பு நிரலுக்குத் திரும்புகிறார். ஒதுக்கப்பட்டது.

பிரச்சனை என்னவென்றால், ஒதுக்கப்பட்ட பகுதி முற்றிலும் மெய்நிகர். உண்மையான நினைவகப் பக்கங்கள் எதுவும் ஒதுக்கப்படவில்லை.

இந்த ஒதுக்கப்பட்ட பிரிவில் இருந்து ஒவ்வொரு பக்கத்திற்கும் முதல் அணுகல் ஏற்படும் போது, ​​MMU ஒரு பக்க பிழையை "சுடுகிறது", அதன் பிறகு அணுகப்படும் மெய்நிகர் பக்கத்திற்கு உண்மையானது ஒதுக்கப்படும்.

எனவே, உண்மையில், நாங்கள் பஸ் மற்றும் ரேம் தொகுதிகளின் செயல்திறனை சோதிக்கவில்லை, ஆனால் இயக்க முறைமையின் MMU மற்றும் VMM இன் செயல்திறனை சோதிக்கிறோம். ரேமின் உண்மையான செயல்திறனை சோதிக்க, ஒதுக்கப்பட்ட பகுதிகளை ஒரு முறை துவக்க வேண்டும். உதாரணமாக இது போன்ற:

#include <sys/time.h>
#include <string.h>
#include <iostream>

#define CNT 1024
#define SIZE (1024*1024)

int main() {
	struct timeval start;
	struct timeval end;
	long millis;
	double gbs;
	char ** buffers;
	buffers = new char*[CNT];
	for (int i=0;i<CNT;i++) {
                // FIXED HERE!!!
		buffers[i] = new char[SIZE](); // Add brackets, &$# !!!
	}
	gettimeofday(&start, NULL);
	for (int i=0;i<CNT;i++) {
		memset(buffers[i], 0, SIZE);
	}
	gettimeofday(&end, NULL);
	millis = (end.tv_sec - start.tv_sec) * 1000 +
		(end.tv_usec - start.tv_usec) / 1000;
	gbs = 1000.0 / millis;
	std::cout << gbs << " GB/sn";
	for (int i=0;i<CNT;i++) {
		delete buffers[i];
	}
	delete buffers;
	return 0;
}

அதாவது, ஒதுக்கப்பட்ட பஃபர்களை இயல்புநிலை மதிப்புடன் (char 0) துவக்குகிறோம்.

பார்க்கலாம்:

$ ./memtest
28.5714 GB / s

மற்றொரு விஷயம்.

கதையின் ஒழுக்கம் - விரைவாக வேலை செய்ய பெரிய இடையகங்கள் தேவைப்பட்டால், அவற்றைத் துவக்க மறக்காதீர்கள்.

ஆதாரம்: www.habr.com

கருத்தைச் சேர்