Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
0 / 0 / 0
Регистрация: 14.06.2017
Сообщений: 1

Очень медленно копирует из буфера в буфер (ОЗУ)

24.06.2017, 16:32. Показов 1268. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер!
Прошу объяснить, в чем причина очень медленного копирования из одного буфера ОЗУ в другой куска файла размером 256 МБ:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
 
 
/* 
 * File:   main.c
 * Created on 24 июня 2017 г., 15:49
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
/*
 * 
 */
int main(int argc, char** argv) {
clock_t currentTime;
 
FILE *fp;
static unsigned char Buff_1[256000320];
static unsigned char Buff_2[256000320]; 
static unsigned char *p1_WR,*p1_RD;
static unsigned long int i;
static unsigned long int Size_input_file;
    
    
    
    // Читаем из исходного файла в массив     
        if ((fp = fopen("/media/victor/MEDIA/Клипы/ROMANTIC ITALIAN MUSIC.mp4", "rb")) == NULL)
        
     {   
         puts("Открыть файл не удалось\n");
         exit(1);
     }                      
        fseek(fp, 0L, SEEK_END);
        Size_input_file = ftell(fp);        
        rewind(fp);              
       
    
        fread((void *)&Buff_1,1,Size_input_file,fp); 
        printf("Размер входного файла %lu байт\n", Size_input_file);
        fclose(fp); 
        
        p1_RD=&Buff_1[0];
        p1_WR=&Buff_2[0];
        i=256000320;
        do
        {
        *p1_WR=*p1_RD;
        p1_RD++;
        p1_WR++;
        }while(--i);
        
        
        currentTime=clock()-currentTime;
        currentTime=(double)currentTime;//CLOCKS_PER_SEC;
        printf("Время исполнения кода %li с\n", currentTime); 
        
        
    return (EXIT_SUCCESS);
}
"Размер входного файла 901996924 байт
Время исполнения кода 2373338 с

ВЫПОЛНЕНИЕ FINISHED; значение выхода 0,; в реальном времени: 3s; пользователь: 950ms; система: 1s"

Ubuntu 16.04, Netbeans,AMD A6-3500 APU with Radeonб 4 GB RAM,

ps
Мучаюсь, уже два дня. На просторах интернета нашел пример на Java, где гуру показывает оптимизацию программы. Так вот, у него программа глотает гигабайтный файл, сортирует по байт-коду в обратном порядке и результат выводит меньше чем за 0,9 с!

Добавлено через 7 минут
i=256000320;
currentTime=clock(); // пропустил
"Время исполнения кода 1416149 с

ВЫПОЛНЕНИЕ FINISHED; значение выхода 0,; в реальном времени: 3s; пользователь: 1s; система: 1s"
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.06.2017, 16:32
Ответы с готовыми решениями:

CopyToClipboard не копирует в буфер обмена
Всем привет. У меня такая проблема, я пытаюсь скопировать текст из поля Edit1 в буфер обмена: Edit1.CopyToClipboard; Но когда я...

Кнопка которая копирует содержимое в буфер обмена
Думаю, тут нет ничего тяжелого но никак не могу разобраться сам. Пишу приложение C# Windows Forms. Нужно чтобы весь текст написанный в...

Без очевидной причины начали очень-очень медленно грузится страницы в браузерах
Без очевидной причины начали очень-очень медленно грузится страницы в браузерах Добавлено через 3 минуты При этом раньше все...

6
153 / 148 / 66
Регистрация: 20.02.2014
Сообщений: 556
24.06.2017, 18:16
Veganin, потому, что нет понимания работы ЭВМ. Копируешь побайтово, а не по размеру машинного слова, не используешь возможности конвеера, выделяешь огромные буферы, работать бы постранично, да и чего греха таить цикл ужасный - зачем то копируешь оставшиеся байты, когда размер файла явно может быть меньше, чем твои константы.. А у Java возможности оптимизации и JIT компилятора явно устроены лучше, чем, прости, конечно, твой код. Чуть попозже скину, конечно, не идеальный, но все же побыстрее работающий код.
1
Заблокирован
24.06.2017, 19:01
Veganin, для копирования памяти есть memcpy. Он еще и векторизованную версию запустит, если твой проц умеет. Ну, и комент Вовани про размер файла - актуален в любом случае.
0
503 / 352 / 94
Регистрация: 22.03.2011
Сообщений: 1,112
28.06.2017, 15:08
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
 
static inline
size_t get_file_size(FILE *fp)
{
    size_t size;
 
    fseek(fp, 0L, SEEK_END);
    size = ftell(fp);
    rewind(fp);
 
    return size;
}
static inline
int64_t timespec_diff_ns(struct timespec begin, struct timespec end)
{
    return (end.tv_sec - begin.tv_sec) * (int64_t)1000000000 + (end.tv_nsec - begin.tv_nsec);
}
 
int main()
{
    struct timespec begin, end;
 
    FILE *fp;
    if ((fp = fopen("/tmp/1G", "rb")) == NULL)
    {
        perror("Can not open file");
        return 1;
    }
 
    size_t size = get_file_size(fp);
    uint8_t *ram = (uint8_t*)malloc(size * sizeof(uint8_t));
 
    clock_gettime(CLOCK_MONOTONIC, &begin);
    char buff[4096];
    for (size_t left = size, r_bytes = 0; left; left -= r_bytes)
    {
        r_bytes = fread(buff, 1, sizeof(buff), fp);
        memcpy(ram, buff, r_bytes);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
 
    fclose(fp);
 
    printf("Elapsed %lld ms\n", timespec_diff_ns(begin, end) / 1000000);
    return 0;
}
236 ms и я ничего не оптимизировал.
0
153 / 148 / 66
Регистрация: 20.02.2014
Сообщений: 556
17.07.2017, 09:12
Цитата Сообщение от Вованя Посмотреть сообщение
Чуть попозже скину
ну точно же, чуток попозже
Код запилен со многими упущениями и предположениями (например, размер страницы и размер кеш-линии), по большей части он представлен для ознакомления, в любом случае компилятор в большинстве случаев может намного лучше выполнить оптимизации(например, за счет использования SIMD-инструкций).
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#if !defined(__GNUC__) || !defined(__linux__)
#error Unsupported platform or compiler!
#endif /* __GNUC__ */
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
 
#if defined(WIDEINT) 
typedef __int128    word_t;
#define WORDSIZEOF  16
#else
typedef long        word_t;
#define WORDSIZEOF  8
#endif /* WIDEINT */
 
#define LINESIZE        64
#define PAGESIZE        8192
 
#define CPYPAGECNT      PAGESIZE / LINESIZE / 2
#define CPYLINEOFFSET   LINESIZE / WORDSIZEOF
#define CPYLINESTEP     CPYLINEOFFSET * 2
 
#define cat_(x, y) x##y
#define cat(x, y) cat_(x, y)
#define lncpy0(d, s, i) d[i] = s[i];
#define lncpy1(d, s) lncpy0(d, s, __COUNTER__)
#define lncpy2(d, s) lncpy1(d, s) lncpy1(d, s)
#define lncpy4(d, s) lncpy2(d, s) lncpy2(d, s)
#define lncpy8(d, s) lncpy4(d, s) lncpy4(d, s)
#define lncpy16(d, s) lncpy8(d, s) lncpy8(d, s)
#define lncopy_(f, d, s) f(d, s)
#define lncopy(dst, src) lncopy_(cat(lncpy, WORDSIZEOF), dst, src)
 
#define errhandler(msg) ({\
    perror("ERROR: " msg); \
    rc = 1; goto cleanup; })
 
#define unlikely(x) \
    __builtin_expect(!!(x), 0)
 
#define reader(fd, buf) ({ \
    __label__ again; \
    ssize_t rb; \
    again: rb = read(fd, buf, sizeof(buf)); \
    if(unlikely(rb == -1)) { \
        if(errno == EINTR) goto again; \
        errhandler("read()"); } rb; })
 
#define forcopy(dst, blksize, estbytes) \
    for(const char *end = dst + (estbytes & ~(blksize - 1)); \
        dst < end; dst += blksize, estbytes -= blksize)
 
static inline void
bytecopy(void * restrict dst, const void * restrict src, size_t len)
{
    if(len == 0) return;
    char *_dst = dst;
    const char *_src = src;
    size_t cnt = (len + 7) / 8;
    switch(len % 8) {
        case 0: do { *_dst++ = *_src++;
        case 7: *_dst++ = *_src++;
        case 6: *_dst++ = *_src++;
        case 5: *_dst++ = *_src++;
        case 4: *_dst++ = *_src++;
        case 3: *_dst++ = *_src++;
        case 2: *_dst++ = *_src++;
        case 1: *_dst++ = *_src++;
        } while(--cnt > 0);
    }
}
 
static inline void
linecopy(void * restrict dst, const void * restrict src)
{
    word_t *_dst = dst;
    const word_t *_src = src;
    lncopy(_dst, _src);
}
 
static inline void
pagecopy(void * restrict dst, const void * restrict src)
{
    word_t *_dst = dst;
    const word_t *_src = src;
    for(int i = 0; i < CPYPAGECNT; ++i, _dst += CPYLINESTEP, _src += CPYLINESTEP) {
        __builtin_prefetch(_src + CPYLINESTEP, 1, 0);
        __builtin_prefetch(_dst + CPYLINESTEP, 0, 0);
        linecopy(_dst, _src);
        linecopy(_dst + CPYLINEOFFSET, _src + CPYLINEOFFSET);
    }
}
 
 
int main(int argc, char *argv[])
{
    struct stat fs;
    ssize_t est, rb;
    int fd, rc = 0, fdo;
    char *dst = NULL, *dstit;
    off64_t offset = PAGESIZE;
    char __attribute__((aligned(PAGESIZE))) iobuf[PAGESIZE];
    
    fd = open(argv[1], O_RDONLY);
    if(fd == -1) {
        errhandler("open()");
    }
 
    fdo = creat(argv[2], 0666);
    if(fdo == -1) {
        errhandler("creat()");
    }
 
    if(fstat(fd, &fs) == -1) {
        errhandler("fstat()");
    }
 
    est = fs.st_size;
    dst = dstit = memalign(PAGESIZE, est);
    if(dst == NULL) {
        errhandler("memalign()");
    }
 
    forcopy(dstit, PAGESIZE, est) {
        readahead(fd, offset, PAGESIZE);
        reader(fd, iobuf);
        pagecopy(dstit, iobuf);
        offset += PAGESIZE;
    }
 
    if(est) {
        rb = reader(fd, iobuf);
        forcopy(dstit, LINESIZE, est) {
            linecopy(dstit, iobuf);
        }
        rb -= est;
        bytecopy(dstit, iobuf + rb - est, est);
    }
 
    if(write(fdo, dst, dstit - dst) == -1) {
        errhandler("write()");
    }
    
cleanup:
    close(fd);
    close(fdo);
    free(dst);
 
    return rc;
}
Компилировать:
gcc -std=gnu99 -O0
0
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
22.07.2017, 21:39
Цитата Сообщение от Veganin Посмотреть сообщение
C
1
2
3
4
5
6
do
* * * * {
* * * * *p1_WR=*p1_RD;
* * * * p1_RD++;
* * * * p1_WR++;
* * * * }while(--i);
1. Адресная арифметика может на конкретном проце скидывать кэш.
2. Компилятор не гений, не смог оптимизировать цикл

Как вариант ввести локальный счётчик типа size_t и реализовать копирование даже побайтово из одной области в другую через for, представив указки на данные в качестве массива - тут уж, думаю, все компиляторы справятся и при дефолтном -О2 оптимизирую копирование под конкретную платформу.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
23.07.2017, 12:47
Цитата Сообщение от Veganin Посмотреть сообщение
Размер входного файла 901996924 байт
Когда файл имеет размер в три раза больше, чем буфер, то программа должна была упасть

Цитата Сообщение от Veganin Посмотреть сообщение
Время исполнения кода 2373338 с
Показывает некорректное значение из-за того, что переменная currentTime не была проинициализирована

Цитата Сообщение от Вованя Посмотреть сообщение
Копируешь побайтово, а не по размеру машинного слова
Есть подозрение, что основное время программы занимает чтение файла большого размера. Неоптимальное копирование из буфера в буфер должно работать в разы быстрее (на фоне чтения файла)

Цитата Сообщение от Вованя Посмотреть сообщение
выделяешь огромные буферы, работать бы постранично
Тут цели программы не озвучены. Т.е. неизвестно, нужно ли иметь в памяти копию целикового файла
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.07.2017, 12:47
Помогаю со студенческими работами здесь

Интернет стал очень и очень медленно работать
здравствуйте, установил семерку, ввиду неопытности в познании кибернаук не могу прочувствовать её приемущество перед XP интернет стал очень...

Почему clipboard.settext(str) копирует текст в буфер обмена без абзацев?
Почему clipboard.settext(str) копирует текст в буфер обмена без абзацев? Например, я скопировал текст в textbox через...

Программа ест очень-очень много ОЗУ
При запуске - 14-16 МБ! А весь &quot;прикол&quot; в том... что на в ней ничего нет! Лишь одна форма - и все! Добавляю пару picturebox ов - уже 25 МБ....

DirectShow воспроизведение видео из буфера в ОЗУ
Подскажите, как на DirectShow воспроизвести файл (а еще лучше - произвольную часть файла), который предварительно считан в буфер в ОЗУ?...

Буфер, ОЗУ, кэш, регистр процессора
Добрый день! Часто задаю вопросы на форуме в процессе изучения C/C++ и вот. Начал читать про трудности использования getchar() ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru