singlepost

многопоточность, как правильно? C++ << На главную или назад  

здравствуйте. такие дела:
пытаюсь считать текст из файла пословно и добавить каждое слово в <map>
<map> определил глобально, файл тоже определен глобально.

функция чтения такая:

UINT reading_th1(LPVOID pParam){

string str;

while (!mfile.eof()){
mfile &gt;&gt; str;
mymap[str]+=1;
}

return 0;
}

из мейна вызываю 4 потока

AfxBeginThread(reading_th1,NULL);
AfxBeginThread(reading_th1,NULL);
AfxBeginThread(reading_th1,NULL);
AfxBeginThread(reading_th1,NULL);

итог 3 состояния:
работает (при этом снижает общее время выполнения программы на несколько секунд, что и требуется)
зависает
ошибка

причем выскакивают рандомно, как понимаю это результат когда потоки одновременно пытаются прочитать файл.

готов слушать ваши ругательста и угрозы побить по рукам, но дайте ссылки или сами напишите примеры и теорию как это использовать ПРАВИЛЬНО. сегодня первый день пытаюсь сам прикрутить потоки к своей программе. а в учебнике вузовском нету )

28 ответов в теме “многопоточность, как правильно? C++”

  1. 28
    ответил:

    HANDLE h=AfxBeginThread(MyFunc,NULL);

    WaitForSingleObject(h,INFINITE);

    он его не ждет)

  2. 27
    Павел Потапов ответил:

    Если не ошибаюсь, то в WaitForSingleObject надо передать HANDLE потока, завершения которого надо дождаться.

  3. 26
    Василий Some ответил:

    1. stl не поддерживает многопоточность (точнее ее не поддерживают большинство реализаций)
    2. следовательно синхронизацию (на любых примитивах) + _не_использовать итераторы – они инвалидируются для мапы при вставке

  4. 25
    ответил:

    спасибо. интересно вас читать. с потоками боле менее хорошо пошло. делаю так как сказал кто то выше, один поток читает файл, другие два прочитанные значения пишут в map

    не могу только пока разобраться как ждать завершение потока с помощью WaitForSingleObject

  5. 24
    Павел Потапов ответил:

    Дмитрий, если Вы не умеете внимательно читать, что написано, то это Ваши проблемы. И не стоит при этом обвинять в других в незнании.

    Еще раз повторяю для Вас:

    Если известно место вставки очередного элемента, например, если в map добавляются элементы ОТСОРТИРОВАННОГО массива, то время вставки меньше логарифма. STL предоставляет инструмент для этого, функция insert возвращая итератор на вставленный элемент. Времени для вставки следующего элемента будет затрачено меньше логарифма.

  6. 23
    Дмитрий Ашкадов ответил:

    для всех тех, кто до сих пор считает, что прав:

    даю на вход последовательность, например, чисел, никак не упорядоченных (вместо чисел – строки из файла, как у автора).

    Ну, предложитеалгоритм быстрее, чем за логарифм

  7. 22
    Василий Степанов ответил:

    #18 //cplusplus.com/reference/stl/map/insert/
    Раздел Complexity.

  8. 21
    Дмитрий Ашкадов ответил:

    Только вот rand() не там )))

  9. 20
    Пашка Джиоев ответил:

    #18 //pastie.org/899458
    результат:
    ============================
    Data size: 100
    InsertSorted: 0 sec.
    InsertSimple: 0 sec.
    ============================
    Data size: 1000
    InsertSorted: 0 sec.
    InsertSimple: 0 sec.
    ============================
    Data size: 10000
    InsertSorted: 0 sec.
    InsertSimple: 0.01 sec.
    ============================
    Data size: 100000
    InsertSorted: 0.01 sec.
    InsertSimple: 0.03 sec.
    ============================
    Data size: 1000000
    InsertSorted: 0.15 sec.
    InsertSimple: 0.42 sec.
    ============================
    Data size: 10000000
    InsertSorted: 1.51 sec.
    InsertSimple: 6.71 sec.

  10. 19
    Денис Лисов ответил:

    #18, если вставляется что-то произвольное, то нельзя. А вот если вам заранее что-то известно про вставляемое – к примеру, что массив вставляемых значений отсортирован – то возможно за счет этого выиграть по сравнению с логарифмом.

  11. 18
    Дмитрий Ашкадов ответил:

    #17, Учи теорию… нельзя, значит нельзя!И это доказано. И спорить ненадо! место вставки еще узнать надо, сказано выше же!

  12. 17
    Павел Потапов ответил:

    #16, получится, если заранее известно место вставки , пример приведен в #13.

  13. 16
    Дмитрий Ашкадов ответил:

    #12, быстрее, чем за логарифм не получится, т.к. это нижняя оценка, т.е."Большая подкова"(Log(N))

  14. 15
    Денис Лисов ответил:

    А если требуется сильно ускорить процесс, я бы на вашем месте попробовал две вещи.
    Во-первых, можно заменить потоковое чтение на fscanf и посмотреть, как изменится скорость.
    Во-вторых, раз вы все равно работаете в MFC, можно воспользоваться CreateFileMapping и MapViewOfFile и работать с файлом из памяти.

  15. 14
    Денис Лисов ответил:

    Первое. Если я не ошибаюсь, STL не гарантирует вам правильной работы при одновременном использовании (для записи) одного объекта из разных потоков. Потому требуется на каждый поток выделить отдельный map, после чего их объединить необходимым вам способом.

    А даже если STL это гарантирует, конструкция mymap[str]+=1; будет вести себя неправильно. Так что тут у вас серьезная проблема.

  16. 13
    Пашка Джиоев ответил:

    У map::insert логарифмическая сложность, за исключением случая, когда пользуешься версией insert( iterator, value), и вставляешь отсортированные данные друг за другом (в параметре iterator передаешь итератор из результата предыдущей вставки) – в этом случае сложность O(1).

  17. 12
    Василий Степанов ответил:

    почему нельзя одним потоком прочитать файл в std::list или даже в std::vector, а уже потом потоками засунуть в std::map?
    или файл настолько большой, что одновременно std::vector и std::map не влезут в память.

    кстати, в курсе про вариант вызова std::map::insert() с алгоритмической сложностью O(1)? может быть это может быть решением проблемы перформанса?

  18. 11
    ответил:

    вопрос, как дождаться завершения потока после его вызова? гуглю не помогает)

  19. 10
    Пашка Джиоев ответил:

    Какой длины строки?
    Если небольшие, то я не понимаю откуда прирос может бытью

  20. 9
    ответил:

    первый том войны и мира – 3мегабайта )

  21. 8
    Сыроватченко Сергей ответил:

    почитай шилда, у него неплохо написана о реализации многопоточности.

  22. 7
    ответил:

    можно ссылочку пожалуйста?

  23. 6
    Дмитрий Ашкадов ответил:

    Работа с диском ой какая тормозная, какой тут может быть прирост, кроме константы? а константный прирост – фигня ненужная

  24. 5
    ответил:

    2Пашка ت Джиоев
    при иногда верной работе программы (без семафоров, щас я их напишу попытаюсь), я получаю прирост 3-4 секунды. что очень для меня хорошо.

  25. 4
    Пашка Джиоев ответил:

    Не думаю, что многопоточное чтение даст прирост производительности, в любом случае чтение надо будет производить последовательно. Вот если бы с каждой считанной строкой надо было производить какие-нибудь трудоемкие действия, то прирост бы был.

  26. 3
    ответил:

    спасибо. инфу нашел. сейчас попробую.

    еще небольшой вопрос:
    можно ли миногопоточно перевести данные из <map> в <multimap> ?
    как реализовать алгоритм? я что то думал, не знаю.

  27. 2
    Евгений Князев ответил:

    открыть для себя семафоры (или замки — частный случай семафора).
    обращаешься к ресурсу (файлу) — закрываешь семафор. Другой поток будет ждать разрешения поработать с ресурсом.
    закончил работать с ресурсом — открыл семафор.

    А тут у тебя ситуация на грани аппаратного deadlock — в один момент времени только один поток имеет право обладать ресурсом.

  28. 1
    Константин Смотритель ответил:

    Медведь, как бы сказать помягче… лучше наводящий вопрос: а какой тип возвращает твоя AfxBeginThread()? Вот, и при чём здесь системный хендл потока?

    А ещё учись пользоваться функцией GetLastError() и утилитой ErrorLookup!

    P.S.Нормальный Win32 пример тут //www.gamedev.net/community/forums/topic.asp?to...

    а тебе надо заюзать это (скопируй ссылку в браузер) //msdn.microsoft.com/en-US/library/afb2xh7f(v=VS.80).aspx

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.