Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Программа не хочет работать на многоядерном процессоре  (Прочитано 22880 раз)
0 Пользователей и 1 Гость смотрят эту тему.
tom4ik85
Участник

ua
Offline Offline
Пол: Мужской

« : 23-02-2009 12:56 » 

Здравствуйте.
Есть программа. Она, по сути, является блоком управления большой системой по Ethernet. Управляет она множеством (пока 20, но может быть до 272) одинаковых СВЧ-блоков. На каждом блоке запущен сервер, а программа к нему подключается, т. е. она клиент. За каждое подключение отвечает один из 20 объектов класса BK.
Этот класс по таймеру проверяет подключение. Прверка - это тестовая посылка. Ответ от блока должен быть такой же и время ответа 500 мс. Если ответа нет, то считаем что блок не подключен. Если Блок не подключен, то раз в секунду пробуем подключится.
В итоге имеем множество таймеров и потоков.
Я писал и компилировал все на 1-ядерной машине. Не было возможности на 2-х или 4-хядерном компе опробовать.
Как оказалось позже программа на 2-хядерном компьютере сильно нагружает 1 процессор. Но это не критично.
Проблемма в том, что она сильно висит. Такое впечатление, что там очень долгие циклы везде. Приотключении 2-ого ядра программа работает абсолютно нормально, т. е. хорошо грузит процессор, но ничего не висит.
Подскажите, пожалуйста, в какую сторону копать и в чем может быть проблемма?
Я думаю, что проблема в синхронизации всех этих опросов подключения на таймерах с работой системы с 2-умя ядрами, но как это решить просто не понимаю.
Или хотя бы можно как-то в программе написать, чтоб она пользовала только одно ядро.

P.S. Пробовал чтавить, чтоб она работала только на 2-ом ядре - та же проблема.

Подскажите, пожалуйста, может кто-то сталкивался с подобным.
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 23-02-2009 14:15 » 

Или хотя бы можно как-то в программе написать, чтоб она пользовала только одно ядро.
Можно конечно привязывать все потоку к одному процессору (считай ядру), смотри системный вызов:
Код:
DWORD_PTR SetThreadAffinityMask (
  HANDLE hThread,                 // handle to thread
  DWORD_PTR dwThreadAffinityMask  // thread affinity mask
);

Советую так же посмотреть в сторону функции:
Код:
BOOL QueueUserWorkItem(
  LPTHREAD_START_ROUTINE Function,  // starting address
  PVOID Context,                    // function data
  ULONG Flags                       // worker options
);
которая позволит организовать работу всего твоего хозяйства в пуле потоков и возложит всю работы по созданию, привязке к процессорам потоков и т.п. на Windows.
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #2 : 24-02-2009 06:10 » 

1. Начни с проблемы производительности. Судя по описанию твоя программа не должна нагружать CPU.
2. Какие общие данные есть у потоков?
3. Как часто происходит проверка подключения и каким образом?
4. Может ты злоупотребаяешь объектами ядра и переключением контекста? (перевыдения памяти, пересоздание сокетов, частое обращение к сокетам и т.д. и т.п.)
5. Какой тип сокетов используется?
6. Второе ядро реальное или виртуальное?
7. Читай побольше Саттера(http://herbsutter.wordpress.com/). Например: http://www.ddj.com/hpc-high-performance-computing/214100002
Записан

Странно всё это....
tom4ik85
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #3 : 24-02-2009 08:44 » 

Спасибо за ответы.
Начну с конца.

7. Буду читать больше, это вообще моя первая программа на С++. Я перечитал множество литературы, и может решил бы эту проблему еще при написании, если бы писал на 2-ядерном процессоре. На 1-ядерном все нормально работало.
6. Второе ядро реальное. Intel CoreDuo E8200 по-моему.
5. Сокет Асинхронный использую.
4. Может и злоупотребляю, но не знаю как можно это посмотреть. У меня были проблемы с памятью, но я переписал немного кода через указатели, а не через статические объекты и стало все нормально. Повторюсь, это моя первая программа и писал я её, скорее всего, далеко не самыми оптимальными методами, но и на 2-ядерном с отключением именно 2-го ядра все нормально работает.
3. Проверка подключения происходит так:
Сокет пробует подключится. Если подключился, то ставлю таймер №1 на 500 мс. По этому таймеру шлем тест-посылку. В методе OnRec() сбрасываю и опять стартую таймер №2 500 мс. Если сработает таймер №2 - то посылка не пришла воворемя. Сокет при этом закрываю, открываю заново и пытаюсь подключится. Извините, в первом посте немного неправду написал (давно программу не видел). Если Сокет не подключен, то я пробую просто подключиться, а не жду 1 секунду. Может здесь много сокетов пересоздаю, но по-другому не получается. Если идет обрыв связи, то сокет не всегда знает, что он отключился и не хочет подключаться. Поэтому я и закрываю его насильно, а потом создаю заново.
2. Про потоки я не правильно, наверное, выразился. Отдельные потоки я не создаю. Я имел ввиду, что сокеты каждый работает в своем потоке. В этом смысле они никак не пересекаются, т.е. между сокетами, да и вообще между объектами взаимосвязи никакой нет.
1. Я бв рад начать с производительности, но не знаю как померять её самую. Да желательно так чтоб поменять что-то в программе и померять, потом опять поменять и посмотреть. Тгда може чисто експериментально найду в чем проблемма. Но как это сделать пока не знаю и если подскажете то буду очень благодарен Улыбаюсь

По поводу SetThreadAffinityMask и QueueUserWorkItem я бы попробовал, но я не создавал сам потоков и где взять хендлы этих потоков не знаю. Извините, что в первом посте не уточнил, писал с помощью MFC и Visual C++ 6.0. в общем с этим буду разбираться и пробовать.

Если кому-то нужно, могу выложить необходимый код кусками. Весь не могу. Начальство сказало, что секрет Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 24-02-2009 15:26 » 

tom4ik85, код с сокетами (CAsyncSocket я так понимаю ?) - в студию!  Как раз трахался с ними, вроде разобрался, как мне кажется, неплохо. ) Вот и увидим Отлично )
Записан

tom4ik85
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #5 : 24-02-2009 19:10 » 

Сначала код класса, который наследует от CAsyncSocket:
Код:
...

CClient::CClient()
{
bIsConnected = FALSE;
m_bIsThisBk = FALSE;
m_nCol = m_nRow = m_nNum = 0;
}

...

void CClient::OnReceive(int nErrorCode)
{
DWORD dwRead = 0;
if(m_bIsThisBk == FALSE)
dwRead = Receive(buf_bps, sizeof(buf_bps));
else
dwRead = Receive(buf, sizeof(buf));

switch(dwRead)
{
case 0:
AfxMessageBox("Error ! Receiving 0");
break;
case SOCKET_ERROR:
AfxMessageBox("Error ! Receiving SOCKET_ERROR");
break;
default:
m_pWnd->SendMessage(CL_REC, 0, (LPARAM) dwRead);

if(m_bIsThisBk == FALSE)
{
for(int i = 0; i<9; i++)
{
g_buf_bps[m_nNum][i] = buf_bps[i];
}
}
else
{
for(int i = 0; i<3; i++)
{
g_buf_bk[m_nCol][m_nRow][i] = buf[i];
}
}
break;
}

CAsyncSocket::OnReceive(nErrorCode);
}

void CClient::OnClose(int nErrorCode)
{
m_pWnd->SendMessage(CL_CLOSED, 0, 0);
CAsyncSocket::OnClose(nErrorCode);
}

void CClient::OnConnect(int nErrorCode)
{
m_pWnd->SendMessage(CL_CONNECT, (WPARAM) nErrorCode, 0);
CAsyncSocket::OnConnect(nErrorCode);
}

...
Я повырезал не особо, на мой взгляд, выжные куски, но прикреплю .cpp и .h обоих этих классов, если нужно посмотреть внимательней.
Но тут ничего особенного не делается. Использование самого сокета в классе блока
Код:
...

CBK::CBK()
{
m_pParent = NULL;

if(m_sClient.Create() == 0) // Создаем сокет
{
DWORD dwError = GetLastError();
CString str;
str.Format("%d on Creating Socket", dwError);
if(dwError != WSAEWOULDBLOCK)
AfxMessageBox(str);
}

m_bIsConnected = FALSE; // сбрасываем флаг подключения
}


/////////////////////////////////////////////////////////////////////////////
// CBK message handlers

void CBK::OnPaint()
{
if(m_bIsConnected == TRUE)
{
// Рисуем подключенный блок
...
}
else
{
// Рисуем не подключенный блок
...
}
}

void CBK::OnRec(WPARAM wParam, LPARAM lParam)
{
KillTimer(1);
SetTimer(1, 500, NULL); // Сбрасываем таймер. Посылка пришла раньше чем через 500 мс
...
}

void CBK::OnConnect(WPARAM wParam, LPARAM lParam)
{
...
if(wParam == 0) // Подключено
{
m_bIsConnected = TRUE;

...

SetTimer(2, 500, NULL); // Устанавливаем таймер, через который будут отсылаться тест-посылки
Invalidate();
}
else // Ошибка при подключении
{
m_bIsConnected = FALSE;

m_sClient.Close();
m_sClient.Create();

Connect(m_strAddress);
Invalidate();
}
}

void CBK::OnClosed(WPARAM wParam, LPARAM lParam)
{
m_bIsConnected = FALSE;

m_sClient.Close(); // На всякий случай закрываем сокет ...
m_sClient.Create(); // ... и создаем его заново
Connect(m_strAddress); // ну и подключаемся
Invalidate();
}

BOOL CBK::Connect(LPCSTR addr)
{
// Функция для подключения. Для упрощения мне жизни

if(m_sClient.Connect(addr, 1032) == 0)
{
DWORD dwError = GetLastError();
CString str;
str.Format("%d on Connect", GetLastError());
if(dwError != WSAEWOULDBLOCK)
{
return FALSE;
}
else
{
return TRUE;
}
}
else
{
return TRUE;
}
}

void CBK::OnChanelSet(WPARAM wParam, LPARAM lParam)
{
// нужно отправить указания на блок

...

m_pParent->SendMessage(BK_SET_CHANEL, (m_nCol - 1)*16 + In, (m_nRow-1)*16 + Out);

if(m_bIsConnected == TRUE)
{
buf_out[0] = 0x07 - In;
buf_out[1] = 0x07 - Out;
buf_out[2] = 0x01;
if(m_sClient.Send(buf_out, sizeof(buf_out)) == SOCKET_ERROR)
{
DWORD dwError = GetLastError();
if(dwError != WSAEWOULDBLOCK)
{
...
OnClosed(0, 0);
}
else
{
...
}
}
}
}

void CBK::OnChanelClean(WPARAM wParam, LPARAM lParam)
{
// Аналогично прошлой функции

...

if(m_bIsConnected == TRUE)
{
buf_out[0] = 0x07 - In;
buf_out[1] = 0x07 - Out;
buf_out[2] = 0x00;
if(m_sClient.Send(buf_out, sizeof(buf_out)) == SOCKET_ERROR)
{
DWORD dwError = GetLastError();
if(dwError != WSAEWOULDBLOCK)
{
...
m_sClient.Close();
m_sClient.Create();
}
else
{
...
}
}
}
}

void CBK::SetParent(CWnd *parent)
{
m_pParent = parent;
}

void CBK::OnTimer(UINT nIDEvent)
{
// Обработка таймеров

if(nIDEvent == 1)
{
// Посылка не дошла обратно за 500 мс

OnClosed(0, 0);
KillTimer(2);
KillTimer(1);
CWnd::OnTimer(nIDEvent);
}

else if(nIDEvent == 2)
{
// Отправить тест-посылку по таймеру

if(m_sClient.Send(buf_out, sizeof(buf_out)) == SOCKET_ERROR)
{
DWORD dwError = GetLastError();
if(dwError != WSAEWOULDBLOCK)
{
...
m_sClient.Close();
m_sClient.Create();
}
else
{
...
}
}
}
CWnd::OnTimer(nIDEvent);
}

...

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

* Client_BK.rar (7.04 Кб - загружено 889 раз.)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 25-02-2009 05:04 » 

tom4ik85, на первый взгляд ничего вроде тормозов не должно вызвать.

1) А вот попутно мысль -
Цитата
На каждом блоке запущен сервер, а программа к нему подключается, т. е. она клиент. За каждое подключение отвечает один из 20 объектов класса BK.

я бы наоборот сделал - печь была бы клиентом, а комп - сервер. Тогда комп бы просто ловил пинги да информацию.

2) Но, поскольку у тебя обратная схема (странная имхо) , то методом научного тыка определи, когда начинаются тормоза -
сначала закомментируй все send. Естественно, работать всё перестанет, но ты проверь - не тогда ли уже тормоза есть ?

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

3) Ещё момент такой - при получении данных, ты отправляешь данные окнам в виде сообщений. Сообщений может быть много, а это тоже потенциальный источник тормозов. Если окно живёт всё время, пока запущена программа, я бы на твоём месте передал в сокет при его создании указатель на окно - и данные скидывал бы через указатель

4) Ещё было бы интересно измерить скорость отработка OnPaint() - поставь в начале GetTickCount и в конце, разницу тоже рисуй на окне. Хотя, там вроде нечему особо тормозить. Единственное, я бы вынес в конструктор окна

Код:
	m_text_tempFont->CreateFont((unsigned char) 16,
pen.CreatePen(PS_SOLID, 1, m_clrPinColor);
connectionPen = new CPen(PS_SOLID, 3, CLR_BLACK);

оо, а что за connectionPen = new CPen( , да ещё и без удаления ? Утечка Улыбаюсь А new вообще зачем ?
« Последнее редактирование: 25-02-2009 05:10 от Алексей1153++ » Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #7 : 25-02-2009 06:18 » 

мне кажется тут всё не правильно, кроме идеи опроса серверов на предмет доступности Улыбаюсь

1. Что за глобальные объекты без синхронизации?
2. почему нельзя клиенту передать указатель на область памяти которую надо заполнять

отступление: как же я не люблю древние-оконную хрень VS 6.0

я бы сделал так:
1. Выкинуть нах обёртку ASyncSocket, использовал бы boost::asio или низкоуровневый socket
2. Заменил бы таймеры на ожидание WaitForSingleObjectEx с указанием времени ожидания
3. при получении данных подымал бы событие ожидаемое в WaitForSingleObjectEx
4. вместо 2 и 3 я бы скорее всего использовал boost::timed_wait Улыбаюсь
5. ожидание ответа возможно делал бы в отдельном потоке через синхронный сокет.
6. если не дождались, то сокету делаем shutdown и начинаем попытки подключится вновь
7. Использовал бы синхронный сокет скорее всего.
8. логику опроса серверов отделил бы от логики GUI
9. Класс опрашивающий сервер должен получить указатель/ссылку на буфер или контейнер, а не по каким-то магическим числам определять куда бы ему данные сбросить.

ну и + замечания алексея касательно GUI, но не пункт 1 Улыбаюсь
идея когда управляющий интерфейс является клиентом является идеологически правильной, представим, что быдет, если воплотить идею Алексея и дополнить это тест-кейсом "смена имени и ip управляющего интерфейса"
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 25-02-2009 06:57 » 

LogRus, ну начинать гон на VC и онка не нужно, это всё рабочее )

CAsyncSocket работает прекрасно (у меня сеть на 50 клиентов).

с таймерами - тут да, я бы если и сделал таймер, то один на все сокеты - тактировал бы просто

насчёт
Цитата
идея когда управляющий интерфейс является клиентом является идеологически правильной

не понимаю, чем неправильно то, что печь должна  подключается к программе ? Ведь программа должна являться центром организации всей системы , и , опять же, избавляемся от опроса, а просто пассивно ждём пинга от печи. Или пакеты с данными
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #9 : 25-02-2009 07:58 » 

теперь перенесём это в другую плоскость: для того, что бы управлять свом веб-сервером, я должен прописать ему мой динамический IP и он будет ломится в мою систему управления им самим Улыбаюсь бугага

1. я гоню не на весь VC, а на конкретную инкарнацию Улыбаюсь

2. а у меня прекрасно работает socket Улыбаюсь

3. общий таймер я бы не стал делать, мне кажется это, как-то коряво с точки зрения ООП, да и таймеры это коряво, ожидание события вот это круто Улыбаюсь, вот так просто не обосновано, круто и всё тут. На самом деле это для меня более прозрачно, т.е. я оправил данные и сразу завис на ожидании в этой же функции, а не предполагаю, что кто-то, когда-то сгенерирует 2 разрозненных события OnTimer и OnReceive

В любом случае, это всё только моё восприятие конкретной задачи и оно не претендует на истину в последней инстанции.
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 25-02-2009 08:11 » 

моё на истину тоже не претендует, моё - на практику.

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

CAsyncSocket - это SOCKET

Код:
class CAsyncSocket : public CObject
{
.....
// Attributes
public:
SOCKET m_hSocket;
....
и набор функций, которые. Ничего страшного Улыбаюсь

про таймер - не всё сделаешь сообщениями, иногда без таймера не обойтись. Например, в случае, когда сервер - это печь и Томчик хочет опрашивать клиентом сервера. (Бедному клиенту надо постоянно подключаться и отключаться Жаль  )

Цитата
2 разрозненных события OnTimer и OnReceive
так не будет:

1) если печь-сервер, а программа-клиент, то OnTimer
2) если печь-клиент, а программа-сервер, то OnReceive
Записан

tom4ik85
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #11 : 25-02-2009 09:44 » 

Спасибо за ответы Улыбаюсь

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

С указателем на окно в сокете попробую. Может что-то и даст ощутимое, но там других сообщений я сам бросаю намного больше, так что не думаю что это так критично. Но попробую.

По поводу OnPaint() посмотрю. Мне самому интересно и я долго решал с ним какую-то проблемму. Уже не помню что именно, но у меня через минуту где-то перестал создаваться контекст рисования временный. Т.е. я создавал временный, там все рисовал, а потом уже переносил все это на экран, а то тормозила отрисовка. Этот метод мне подсказали на этом форуме давно, если не ошибаюсь, именно Алексей1153++. За что ему отдельное спасибо Улыбаюсь

И пересмотрю и поубираю такого рода утечки, если айду по тексту Улыбаюсь

LogRus-у

Может все и неправильно, я в этом практически не сомневался, но на работе кроме меня программирования все боятся, а мне интересно было, поэтому начал писать. До этого был опыт программирования на "Робике" - такая приставка к телевизору, которая basic понимает Улыбаюсь

По остальным предложениям. Я пробовал это сделать на синхронном сокете, но сильно запутался с потоками, а без потоков не работало как нужно.
boost::timed_wait и boost::asio мне не знакомы и врядли смогу быстро подружиться, а программу заставить работать нужно побыстрее.

Я вообще старался отделить логику сокетов и графики Улыбаюсь Наверное, не очень получилось Улыбаюсь

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

Еще раз спасибо большое за ответы Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 25-02-2009 10:13 » 

у меня в дополнительных потоках необходимость возникла только при отправке больших объёмов данных )
То есть, когда надо большой блок перекинуть - запускаю поток, в который передаю массив, поток кидает через Send порциями данные. Если возвращается -1 , и ошибка - WSAEWOULDBLOCK, жду 100мс и снова пробую. Основной поток не тормозит при этом
Записан

tom4ik85
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #13 : 25-02-2009 12:17 » 

Сейчас расскажу как пробовал я.
Например, есть 2 блока подключеных. Использую синхронный сокет и пытаюсь отправлять постоянно одному и другому информацию.
Если первый отключился, то на время ожидания в WaitForSingleObject программа виснет. Если таких блока будет 2-5, то ничего страшного, а система рассчитана на 272 блока и если 10 из них перехотят отвечать (свич сгорел), то получатся значительные задержки.
Еще раз повторюсь, что первая программа, поэтому может неправильно понимаю суть процессов, но с синхронным точно пробовал и интересно тогда было именно отключение неожиданное одного из блоков, потому как прописано в ТЗ.

наверное я что-то недопонимаю, ра у всех работает, а у меня что-то тормозит и виснет Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 25-02-2009 12:42 » 

tom4ik85, может, причина не в сокете вовсе ? Вот если бы ты вот точно определил, когда зависоны происходят...
Записан

tom4ik85
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #15 : 25-02-2009 12:54 » 

Я запускаю программу, когда она просто не может подключится куда-то. Сетка есть, но блоков, на которых сервера стоят нет. Она вообще не тормозит и ничего не делает Улыбаюсь Возможность проверить с сендами будет только на выходных. Спасибо за помощь. Буду пробовать все вышесказанное, но если вдруг кого-то осенит в чем может быть причина, то пожалуйста пишите.
Дело в том, что сейчас она работает на 1-ядерных и на 2-хядерных с отключенным 2-ым ядром.
Именно это мне показалось очень странным, и вообще я долго искал причину тормозов, пока не увидел что именно с ядрами проблема Улыбаюсь
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #16 : 25-02-2009 13:14 » 

дык ждать надо в отдельном потоке.
Записан

Странно всё это....
tom4ik85
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #17 : 25-02-2009 13:24 » 

Я догадываюсь, что ждать нужно в отдельном потоке, чтоб не тормозить программу, но с потоками пытался подружиться - не получилось.
Я там чего-то не понимаю. Вернее вроде все понятно, но реализовать не могу. Если бы был рядом человек, который на пальцах рассказал бы на примере, может и понял бы. А так пробовал и как собака. Понимать понимаю, а сделать не могу Жаль
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 25-02-2009 17:03 » 

tom4ik85, без паники Улыбаюсь

1) исправь работу с объектами GUI , уточни насчёт того new (а он там вообще нафиг не нужен)
2) сообщения к окнам замени на работу через указатели
3) прикрепи исправленный код (вернее - разрешённую часть Улыбаюсь )

ещё попробуй выполнить программу вообще с пустым OnPaint/

мысль насчёт потоков: с одним ядром не тормозит, с двумя тормозит. Проверь, есть ли тормоза , когда 2 ядра, а подключение всего одно. Потом с двумя подключениями. Когда тормоза появятся ?
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #19 : 26-02-2009 04:49 » 

я давал ссылку. почитайте, я же не просто так её дал Улыбаюсь
Записан

Странно всё это....
tom4ik85
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #20 : 26-02-2009 15:19 » 

Я читал, но не все понял. Нужно со словарем почитать, а словарь дома.
Хватит ли мне для синхронизации доступа к глобальным переменным использования критических секций?
Насколько я понял должно хватить. Т.е. я просто все операции с глобальными переменными заключу в EnterCriticalSection() LeaveCriticalSection().
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 26-02-2009 17:50 » 

tom4ik85, ктритической секции достаточно, если внутри одного процесса всё происходит

Код:
CCriticalSection g_crisec1;


...

if(g_crisec1.Lock(10))
{
  __try
  {
    работаем с переменными, долго тут задерживаться не стОит, всё как можно быстрее
  }
  __finally
  {
    //сюда попадём в любом случае
    g_crisec1.Unlock();
  }
}
Записан

tom4ik85
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #22 : 26-02-2009 19:37 » 

Спасибо. Попробую.
Долго там задерживаться не получится, так как там чтение/запись в буфер.
Это я так понял класс из MFC. Я просто видел пример на EnterCriticalSection() LeaveCriticalSection(). Там еще нужна инициализиция этой переменной.
А здесь нет? Или она в конструкторе CCriticalSection должна быть?

В любом случае, спасибо Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #23 : 27-02-2009 05:16 » 

CCriticalSection g_crisec1; - это глобальная переменная (не обязательно совсем глобальная, а , например, член класса, внутри которого используется синхронизация. Если в нескольких классах - то передавать туда указатели, либо сделать совсем глобальной )) )

инициализировать не надо, конструктор без параметров. В принципе, можно обойтись и без __try __finally , если ты уверен, что после Lock ты не забудешь вызвать Unlock

Ну а можешь обернуть крисек, чтобы в деструкторе обёртки Unlock вызвался автоматом, если был вызвал Lock
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines