ಕೆಟ್ಟ ಪರೀಕ್ಷೆಯ ಬಗ್ಗೆ ಸ್ವಲ್ಪ ಹೆಚ್ಚು

ಒಂದು ದಿನ ನಾನು ಆಕಸ್ಮಿಕವಾಗಿ ತನ್ನ ವರ್ಚುವಲ್ ಗಣಕದಲ್ಲಿ RAM ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಲು ಪ್ರಯತ್ನಿಸುತ್ತಿರುವ ಕೋಡ್ ಅನ್ನು ನೋಡಿದೆ. ನಾನು ಈ ಕೋಡ್ ಅನ್ನು ನೀಡುವುದಿಲ್ಲ (ಅಲ್ಲಿ "ಕಾಲುಬಟ್ಟೆ" ಇದೆ) ಮತ್ತು ನಾನು ಅತ್ಯಂತ ಅಗತ್ಯವನ್ನು ಮಾತ್ರ ಬಿಡುತ್ತೇನೆ. ಆದ್ದರಿಂದ, ಬೆಕ್ಕು ಸ್ಟುಡಿಯೋದಲ್ಲಿದೆ!

#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, ಪ್ರೊಸೆಸರ್ ಬಹುತೇಕ ಲೋಡ್ ಆಗಿಲ್ಲ - ಏಕೆ?!?!

ಉತ್ತರ, ಯಾವಾಗಲೂ, ಅಸಾಮಾನ್ಯವಾಗಿ ಸಾಮಾನ್ಯವಾಗಿದೆ.

ಹೊಸ ಆಪರೇಟರ್ (ಮಾಲೋಕ್ ಫಂಕ್ಷನ್‌ನಂತೆ) ವಾಸ್ತವವಾಗಿ ಮೆಮೊರಿಯನ್ನು ನಿಯೋಜಿಸುವುದಿಲ್ಲ. ಈ ಕರೆಯೊಂದಿಗೆ, ಹಂಚಿಕೆದಾರರು ಮೆಮೊರಿ ಪೂಲ್‌ನಲ್ಲಿನ ಉಚಿತ ಸ್ಥಳಗಳ ಪಟ್ಟಿಯನ್ನು ನೋಡುತ್ತಾರೆ, ಮತ್ತು ಯಾವುದೂ ಇಲ್ಲದಿದ್ದರೆ, ಡೇಟಾ ವಿಭಾಗವನ್ನು ಹೆಚ್ಚಿಸಲು sbrk() ಗೆ ಕರೆ ಮಾಡಿ, ತದನಂತರ ಹೊಸ ಸ್ಥಳದಿಂದ ವಿಳಾಸದ ಉಲ್ಲೇಖವನ್ನು ಪ್ರೋಗ್ರಾಂಗೆ ಹಿಂತಿರುಗಿಸುತ್ತದೆ. ಹಂಚಿಕೆ.

ಸಮಸ್ಯೆಯೆಂದರೆ ಮಂಜೂರು ಮಾಡಿದ ಪ್ರದೇಶವು ಸಂಪೂರ್ಣವಾಗಿ ವರ್ಚುವಲ್ ಆಗಿದೆ. ಯಾವುದೇ ನೈಜ ಮೆಮೊರಿ ಪುಟಗಳನ್ನು ನಿಯೋಜಿಸಲಾಗಿಲ್ಲ.

ಮತ್ತು ಈ ನಿಯೋಜಿತ ವಿಭಾಗದಿಂದ ಪ್ರತಿ ಪುಟಕ್ಕೆ ಮೊದಲ ಪ್ರವೇಶವು ಸಂಭವಿಸಿದಾಗ, MMU ಪುಟದ ದೋಷವನ್ನು "ಶೂಟ್" ಮಾಡುತ್ತದೆ, ಅದರ ನಂತರ ಪ್ರವೇಶಿಸುವ ವರ್ಚುವಲ್ ಪುಟವನ್ನು ನೈಜವಾಗಿ ನಿಯೋಜಿಸಲಾಗುತ್ತದೆ.

ಆದ್ದರಿಂದ, ವಾಸ್ತವವಾಗಿ, ನಾವು ಬಸ್ ಮತ್ತು RAM ಮಾಡ್ಯೂಲ್ಗಳ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಪರೀಕ್ಷಿಸುತ್ತಿಲ್ಲ, ಆದರೆ ಆಪರೇಟಿಂಗ್ ಸಿಸ್ಟಮ್ನ MMU ಮತ್ತು VMM ನ ಕಾರ್ಯಕ್ಷಮತೆ. ಮತ್ತು RAM ನ ನೈಜ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಪರೀಕ್ಷಿಸಲು, ನಾವು ನಿಗದಿಪಡಿಸಿದ ಪ್ರದೇಶಗಳನ್ನು ಒಮ್ಮೆ ಪ್ರಾರಂಭಿಸಬೇಕಾಗಿದೆ. ಉದಾಹರಣೆಗೆ ಈ ರೀತಿ:

#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;
}

ಅಂದರೆ, ನಾವು ಡೀಫಾಲ್ಟ್ ಮೌಲ್ಯದೊಂದಿಗೆ (ಚಾರ್ 0) ನಿಯೋಜಿಸಲಾದ ಬಫರ್‌ಗಳನ್ನು ಸರಳವಾಗಿ ಪ್ರಾರಂಭಿಸುತ್ತೇವೆ.

ನಾವು ಪರಿಶೀಲಿಸುತ್ತೇವೆ:

$./memtest
28.5714 GB / s

ಮತ್ತೊಂದು ವಿಷಯ.

ಕಥೆಯ ನೈತಿಕತೆ - ತ್ವರಿತವಾಗಿ ಕೆಲಸ ಮಾಡಲು ನಿಮಗೆ ದೊಡ್ಡ ಬಫರ್‌ಗಳು ಅಗತ್ಯವಿದ್ದರೆ, ಅವುಗಳನ್ನು ಪ್ರಾರಂಭಿಸಲು ಮರೆಯಬೇಡಿ.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ