Aðeins meira um slæm próf

Einn daginn rakst ég óvart á kóða sem notandi var að reyna að fylgjast með vinnsluminni í sýndarvélinni sinni. Ég mun ekki gefa þennan kóða (það er „fótaklútur“ þar) og ég mun aðeins skilja eftir það mikilvægasta. Svo, kötturinn er í vinnustofunni!

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

Það er einfalt - úthlutaðu minni og skrifaðu eitt gígabæt inn í það. Og hvað sýnir þetta próf?

$ ./memtest
4.06504 GB / s

Um það bil 4GB/s.

Hvað?!?!

Hvernig?!?!?

Þetta er Core i7 (þó ekki það nýjasta), DDR4, örgjörvinn er nánast ekki hlaðinn - AFHVERJU?!?!

Svarið, eins og alltaf, er óvenjulega venjulegt.

Nýi rekstraraðilinn (eins og malloc aðgerðin, við the vegur) úthlutar í raun ekki minni. Með þessu símtali lítur úthlutunaraðilinn á listann yfir lausar staðsetningar í minnisafninu og ef þær eru engar kallar hann sbrk() til að auka gagnahlutann og skilar síðan tilvísun í slóðina frá nýja staðsetningunni í forritið. úthlutað.

Vandamálið er að úthlutað svæði er algjörlega raunverulegt. Engum raunverulegum minnissíðum er úthlutað.

Og þegar fyrsti aðgangurinn að hverri síðu frá þessum úthlutaða hluta á sér stað, „skýtur“ MMU síðuvillu, eftir það er sýndarsíðunni sem verið er að opna á úthlutað raunverulegri.

Þess vegna erum við í raun ekki að prófa frammistöðu strætó- og vinnsluminni eininganna, heldur frammistöðu MMU og VMM stýrikerfisins. Og til þess að prófa raunverulegan árangur vinnsluminni, þurfum við bara að frumstilla úthlutað svæði einu sinni. Til dæmis svona:

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

Það er, við frumstillum einfaldlega úthlutaða biðminni með sjálfgefna gildinu (char 0).

Við athugum:

$ ./memtest
28.5714 GB / s

Annar hlutur.

Mórall sögunnar - ef þú þarft stóra biðminni til að vinna hratt, ekki gleyma að frumstilla þá.

Heimild: www.habr.com

Bæta við athugasemd