+7 (495) 229-0436   shopadmin@itshop.ru 119334, г. Москва, ул. Бардина, д. 4, корп. 3
 
 
Вход
 
 
Каталог
 
 
Подписка на новости
Новости ITShop
Windows 7 и Office: Новости и советы
Обучение и сертификация Microsoft
Вопросы и ответы по MSSQLServer
Delphi - проблемы и решения
Adobe Photoshop: алхимия дизайна
 
Ваш отзыв
Оцените качество магазина ITShop.ru на Яндекс.Маркете. Если вам нравится наш магазин - скажите об этом Google!
 
 
Способы оплаты
 
Курс расчета
 
 1 у.е. = 92.01 руб.
 
 Цены показывать:
 
 
 
 
  
Новости, статьи, акции
 

Ускоряем OpenMP в Visual C++

21.11.2012 17:40
infsega

Одним из популярных и дешёвых средств реализации многопоточных вычислений на языке C++ является OpenMP.

Достоинства технологии очевидны: простота; малые, и легко отключаемые изменения в коде; поддержка от авторов самых популярных компиляторов:

Проверка боем проходит успешно, и вот распараллеленный код проникает в самые укромные уголки проекта, бьёт все рекорды производительности, выдавая шикарную статистику, подтверждающую успешность релиза.

Проходит пара лет, вы успешно мигрируете на Visual Studio 2010,… и обнаруживаете себя сидящим в луже. Если вчера обработка большого массива данных на машинах с многоядерными процессорами проходила за считанные секунды, то сегодня наличие любого фонового приложения, занимающего собственными вычислениями одно или несколько ядер, практически вешает приложение.

Почему так происходит, и как с этим бороться?


В новой реализации OpenMP перед тем, как выйти из активной области в состояние Idle, ваша программа будет ждать завершения операций ввода/вывода, причём ждать с помощью активного SpinWait.

Т.е. если мы с помощью OMP создали N потоков (по 1 на ядро), и неожиданно выяснили, что одно из ядер занято другим приложением, то с большой вероятностью на одном ядре будут выполняться 2 и больше потоков, переключение между которыми будет перемежаться 200-миллисекундными паузами.

Но в рассчётных программах мы не хотим никаких дополнительных синхронизаций!
Разработчики Intel об этом знают, и предлагают пользователю самому заботиться о дополнительных ограничениях с помощью опции kmp_set_blocktime(). К сожалению, их коллеги из Microsoft решили не путать пользователей лишними настройками.

Если переписывать программу на честный threading pool лень или не позволяет религия - предлагаю воспользоваться моим опытом… даунгрейда OpenMP на оригинальную версию из Microsoft Visual Studio 2005. Также инструкция подходит для Visual Studio 2008 с минимальными изменениями.

Во-первых, скопируем в отдельную папку vcomp.lib, vcompd.lib из комплекта Visual C++ 2005 (можно ссылаться напрямую на установленный дистрибутив, но это не так удобно). Заходим в свойства использующих OpenMP проектов, и добавляем в "Additional Library Directories" нашу директорию. Вуаля - теперь проект линкуется с "правильной", быстро работающей версией OpenMP.

Но это ещё не все. Заменим включение <omp.h> заголовочным файлом следующего содержания:

#pragma once

#include <omp.h>

#ifndef __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX
#define __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX "Microsoft.VC80"
#endif

#ifndef _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN
#define _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "1fc8b3b9a1e18e3b"
#endif

#ifndef __OMP_CRT_ASSEMBLY_VERSION
#define __OMP_CRT_ASSEMBLY_VERSION "8.0.50727.762"
#endif

#if defined(_DEBUG)

#if defined(_M_IX86)
#pragma comment(linker,"/manifestdependency:\"type='win32' "              "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' "           "version='" __OMP_CRT_ASSEMBLY_VERSION "' "                            "processorArchitecture='x86' "                                    "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#elif defined(_M_AMD64)
#pragma comment(linker,"/manifestdependency:\"type='win32' "              "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' "           "version='" __OMP_CRT_ASSEMBLY_VERSION "' "                            "processorArchitecture='amd64' "                                    "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#elif defined(_M_IA64)
#pragma comment(linker,"/manifestdependency:\"type='win32' "              "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' "           "version='" __OMP_CRT_ASSEMBLY_VERSION "' "                            "processorArchitecture='ia64' "                                    "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#endif

#else   // _DEBUG

#if defined(_M_IX86)
#pragma comment(linker,"/manifestdependency:\"type='win32' "              "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' "                "version='" __OMP_CRT_ASSEMBLY_VERSION "' "                            "processorArchitecture='x86' "                                    "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#elif defined(_M_AMD64)
#pragma comment(linker,"/manifestdependency:\"type='win32' "              "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' "                "version='" __OMP_CRT_ASSEMBLY_VERSION "' "                            "processorArchitecture='amd64' "                                    "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#elif defined(_M_IA64)
#pragma comment(linker,"/manifestdependency:\"type='win32' "              "name='" __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' "                "version='" __OMP_CRT_ASSEMBLY_VERSION "' "                            "processorArchitecture='ia64' "                                    "publicKeyToken='" _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#endif

#endif  // _DEBUG

Это необходимо для корректной подгрузки манифеста в исполняемых и .dll-файлах. Не забудьте, что даже если OpenMP используется в подгружаемых .dll-файлах, манифест нужно прописать и для исполняемого файла!

Значения __OMP_LIBRARIES_ASSEMBLY_NAME_PREFIX, _OMP_VC_ASSEMBLY_PUBLICKEYTOKEN и __OMP_CRT_ASSEMBLY_VERSION взяты из <crtassem.h>, входящего в поставку Visual C++ 2005. Если у вас стоит другая версия (например, не установлен SP1), то указанные числа нужно заменить на собственные значения

Проект по-прежнему не собирается - сейчас студия возмущена до предела тем, что не определён символ __You_must_link_with_Microsoft_OpenMP_library.

Да, это был очень тонкий намёк со стороны компилятора.

Посмотрим на содержимое сгенерированного .obj-файла. На мой взгляд, лучше всего для этого подойдёт утилита objconv в режиме дизассемблера.

Выясняем, что нам нужно определить переменную размера byte с указанным именем. К сожалению, в C и C++ мы не сможем с точностью воссоздать импортируемый символ, поэтому придётся воспользоваться MASM32.

Добавляем бессмысленную переменную:

PUBLIC __You_must_link_with_Microsoft_OpenMP_library
    data segment
        __You_must_link_with_Microsoft_OpenMP_library db 1
    data ends
end

компилируем:

ml /c antiomp.asm

и полученный на выходе antiomp.obj добавляем в Additional Input проектов, использующих OpenMP.

Всё - у нас должен был получиться рабочий код. Проверить версию OpenMP можно двумя способами:

  1. запустить приложение, подцепиться отладчиком и найти в списке загруженных модулей (Debug/Windows/Modules) библиотеку OpenMP
  2. попытаться найти в исполняемых файлах подстроку vcomp100. Если всё сделано по инструкции, то этой строчки быть не должно

Приятного параллельного программирования!

Ссылки по теме

  
Помощь
Задать вопрос
 программы
 обучение
 экзамены
 компьютеры
Бесплатный звонок
ICQ-консультанты
Skype-консультанты

Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 
Бестселлеры
Курсы обучения "Atlassian JIRA - система управления проектами и задачами на предприятии"
Microsoft Windows 10 Профессиональная 32-bit/64-bit. Все языки. Электронный ключ
Microsoft Office для Дома и Учебы 2019. Все языки. Электронный ключ
Курс "Oracle. Программирование на SQL и PL/SQL"
Курс "Основы TOGAF® 9"
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год. Электронный ключ
Курс "Нотация BPMN 2.0. Ее использование для моделирования бизнес-процессов и их регламентации"
 

О нас
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

На протяжении многих лет интернет-магазин предлагает товары и услуги, ориентированные на бизнес-пользователей и специалистов по информационным технологиям.

Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе.

В нашем магазине вы можете приобрести лицензионное ПО выбрав необходимое из широкого спектра и ассортимента по самым доступным ценам. Наши менеджеры любезно помогут определиться с выбором ПО, которое необходимо именно вам. Также мы проводим учебные курсы. Мы приглашаем к сотрудничеству учебные центры, организаторов семинаров и бизнес-тренингов, преподавателей. Сфера сотрудничества - продвижение бизнес-тренингов и курсов обучения по информационным технологиям.



 

О нас

 
Главная
Каталог
Новинки
Акции
Вакансии
 

Помощь

 
Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 

Способы оплаты

 

Проекты Interface Ltd.

 
Interface.ru   ITShop.ru   Interface.ru/training   Olap.ru   ITnews.ru  
 

119334, г. Москва, ул. Бардина, д. 4, корп. 3
+7 (495) 229-0436   shopadmin@itshop.ru
Проверить аттестат
© ООО "Interface Ltd."
Продаем программное обеспечение с 1990 года