Вот простой тег пропускной способности memset
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main()
{
unsigned long n, r, i;
unsigned char *p;
clock_t c0, c1;
double elapsed;
n = 1000 * 1000 * 1000; /* GB */
r = 100; /* repeat */
p = calloc(n, 1);
c0 = clock();
for(i = 0; i < r; ++i) {
memset(p, (int)i, n);
printf("%4d/%4ld\r", p[0], r); /* "use" the result */
fflush(stdout);
}
c1 = clock();
elapsed = (c1 - c0) / (double)CLOCKS_PER_SEC;
printf("Bandwidth = %6.3f GB/s (Giga = 10^9)\n", (double)n * r / elapsed / 1e9);
free(p);
}
В моей системе (подробности ниже) с одним модулем памяти DDR3-1600 он выводит:
Полоса пропускания = 4.751 ГБ/с (Giga = 10 ^ 9)
Это 37% от теоретической скорости RAM: 1.6 GHz * 8 bytes = 12.8 GB/s
С другой стороны, здесь аналогичный "прочитанный" тест:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
unsigned long do_xor(const unsigned long* p, unsigned long n)
{
unsigned long i, x = 0;
for(i = 0; i < n; ++i)
x ^= p[i];
return x;
}
int main()
{
unsigned long n, r, i;
unsigned long *p;
clock_t c0, c1;
double elapsed;
n = 1000 * 1000 * 1000; /* GB */
r = 100; /* repeat */
p = calloc(n/sizeof(unsigned long), sizeof(unsigned long));
c0 = clock();
for(i = 0; i < r; ++i) {
p[0] = do_xor(p, n / sizeof(unsigned long)); /* "use" the result */
printf("%4ld/%4ld\r", i, r);
fflush(stdout);
}
c1 = clock();
elapsed = (c1 - c0) / (double)CLOCKS_PER_SEC;
printf("Bandwidth = %6.3f GB/s (Giga = 10^9)\n", (double)n * r / elapsed / 1e9);
free(p);
}
Он выводит:
Полоса пропускания = 11,516 ГБ/с (Giga = 10 ^ 9)
Я могу приблизиться к теоретическому пределу для производительности чтения, например, XORing большого массива, но запись кажется намного медленнее. Почему?
ОС Ubuntu 14.04 AMD64 (компилируется с помощью gcc -O3
. Использование -O3 -march=native
делает производительность чтения немного хуже, но не влияет на memset
)
CPU Xeon E5-2630 v2
ОЗУ Один "16 ГБ PC3-12800 Parity REG CL11 240-Pin DIMM" (что он говорит на ящике) Я думаю, что наличие единого DIMM делает производительность более предсказуемой. Я предполагаю, что с 4 модулями DIMM memset
будет работать в 4 раза быстрее.
Материнская плата Supermicro X9DRG-QF (поддерживает 4-канальную память)
Дополнительная система: ноутбук с 2x 4 ГБ оперативной памяти DDR3-1067: чтение и запись составляют около 5.5 ГБ/с, но обратите внимание, что он использует 2 модуля DIMM.
P.S. замена memset
на эту версию приводит к точно такой же производительности
void *my_memset(void *s, int c, size_t n)
{
unsigned long i = 0;
for(i = 0; i < n; ++i)
((char*)s)[i] = (char)c;
return s;
}