• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

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

    Запись на курс до 25 апреля. Получить промодоступ ...

Вопрос по потокам

  • Автор темы Gwyllum
  • Дата начала
Статус
Закрыто для дальнейших ответов.
G

Gwyllum

Суть моей программы - показать, что распараллеливание программы на двухъядерном процессоре способно увеличить скорость вычислений. Программа довольно проста - есть массив из 12 элементов. Программа сперва вычисляет значение каждого. Затем вычисления проводятся с помощью одного процесса. Затем массив разбивается на две части, каждую из которых вычисляют два процесса. Затем на три, на четыре, шесть и двенадцать. Программа замеряет время и строит график.
Как оказалось, время вычисления на двухядернике одним потоком, занимает больше времени, чем обычным кодом. При разбиении на два процесса, это время уменьшается, но при трех - немного увеличивается и т.п. По идее, при вычислении на одноядерном процессоре, разбиение на два потока должно занять больше времени, чем обычное, т.к. тратится дополнительное время на открытие потоков и т.п. Но, результаты приблизительно такие-же.
Подскажите, может в потоках используются какие-то ускоряющие вычисления методы или просто где-то в коде моем ошибка? Пожалуйста, не судите за качество кода - я еще новичок :)

<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">код</div></div><div class="sp-body"><div class="sp-content">
C++:
#define ITER 999999
double result[12];
LPVOID atr[2];
DWORD time[7];
DWORD coords[7];
DWORD maxTime;
DWORD WINAPI Calculate(LPVOID value)// function calculate all values
{
int x=11;
int number=(int)atr[1];

for (int j=(int)value*number; j<(int)value*number+number; j++)
{
for (int i=0; i<ITER; i++)
{
result[j]=result[j]+(sqrt(sin((double)x)+cos((double)x ))-sqrt(acos((double)x)+asin((double)x )) );

}
}

return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(msg)
{
case WM_CREATE:
{

return 0;
}break;
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;

}break;

case WM_PAINT:
{
InvalidateRect(hwnd, NULL, FALSE);
hdc=BeginPaint(hwnd, &ps);
SelectObject(hdc, penWhite);
SetTextColor(hdc, RGB(255,255,255));
SetBkColor(hdc, RGB(0,0,0));
TextOut(hdc, 20,30,(LPCWSTR)szTitle,6);
MoveToEx(hdc, 50,700, NULL);
LineTo(hdc, 50,50);
MoveToEx(hdc, 50,700, NULL);
LineTo(hdc, 950,700);
for (int i=0; i<7; i++)
{
Ellipse(hdc,i*150+45,693,i*150+45+1 0,703);
}
SelectObject(hdc, penGray);

for (int i=1; i<7; i++)
{
MoveToEx(hdc, i*150+50, 700, NULL);
LineTo(hdc, i*150+50,50);
}
SelectObject(hdc, penGreen);
MoveToEx(hdc, 50, 750-coords[0], NULL);
for (int i=0; i<7; i++)
{

LineTo(hdc, i*150+50,750- coords[i]);
}
EndPaint(hwnd, &ps);
DeleteObject(penWhite);
return 0;
}break;

default: break;
}

return (DefWindowProc(hwnd, msg, wparam, lparam));
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpcmdline, int ncmdshow)
{ HANDLE thread0;
HANDLE thread2[2];
HANDLE thread3[3];
HANDLE thread4[4];
HANDLE thread6[6];
HANDLE thread12[12];
DWORD thread_id[27];
for (int i=0; i<12; i++)
{
result[i]=1;
}
int x=11;
DWORD startTime=GetTickCount();//get start time
for (int j=0; j<12; j++)
{
for (int i=0; i<ITER; i++)
{

result[j]=result[j]+(sqrt(sin((double)x)+cos((double)x ))-sqrt(acos((double)x)+asin((double)x )) );

}
}
time[0]=GetTickCount()-startTime;// calculate time running
atr[0]=LPVOID(1);
atr[1]=LPVOID(12);
for (int i=0; i<12; i++)
{
result[i]=1;
}
startTime=GetTickCount();
thread0=CreateThread(NULL, 0, Calculate, (LPVOID)0, 0, &thread_id[0]);
WaitForSingleObject(thread0, INFINITE);
CloseHandle(thread0);
time[1]=GetTickCount()-startTime;
atr[0]=LPVOID(2);
atr[1]=LPVOID(6);

for (int i=0; i<12; i++)
{
result[i]=1;
}
startTime=GetTickCount();
for (int i=0; i<(int)atr[0]; i++)
{
thread2[i]=CreateThread(NULL, 0, Calculate, (LPVOID)i, 0, &thread_id[i+1]);
}
WaitForMultipleObjects(2, thread2, TRUE, INFINITE);
for (int i=0; i<(int)atr[0]; i++)
{
CloseHandle(thread2[i]);
}
time[2]=GetTickCount()-startTime;
atr[0]=LPVOID(3);
atr[1]=LPVOID(4);
for (int i=0; i<12; i++)
{
result[i]=1;
}
startTime=GetTickCount();
for (int i=0; i<(int)atr[0]; i++)
{ thread3[i]=CreateThread(NULL, 0, Calculate, (LPVOID)i, 0, &thread_id[i+3]);
}
WaitForMultipleObjects(3, thread3, TRUE, INFINITE);
for (int i=0; i<(int)atr[0]; i++)
{
CloseHandle(thread3[i]);
}
time[3]=GetTickCount()-startTime;
atr[0]=LPVOID(4);
atr[1]=LPVOID(3);

for (int i=0; i<12; i++)
{
result[i]=1;
}
startTime=GetTickCount();
for (int i=0; i<(int)atr[0]; i++)
{
thread4[i]=CreateThread(NULL, 0, Calculate, (LPVOID)i, 0, &thread_id[i+6]);
}
WaitForMultipleObjects(4, thread4, TRUE, INFINITE);
for (int i=0; i<(int)atr[0]; i++)
{
CloseHandle(thread4[i]);
}
time[4]=GetTickCount()-startTime;
atr[0]=LPVOID(6);
atr[1]=LPVOID(2);

for (int i=0; i<12; i++)
{
result[i]=1;
}
startTime=GetTickCount();
for (int i=0; i<(int)atr[0]; i++)
{
thread6[i]=CreateThread(NULL, 0, Calculate, (LPVOID)i, 0, &thread_id[i+10]);
}
WaitForMultipleObjects(6, thread6, TRUE, INFINITE);
for (int i=0; i<(int)atr[0]; i++)
{
CloseHandle(thread6[i]);
}
time[5]=GetTickCount()-startTime;
atr[0]=LPVOID(12);
atr[1]=LPVOID(1);

for (int i=0; i<12; i++)
{
result[i]=1;
}
startTime=GetTickCount();
for (int i=0; i<(int)atr[0]; i++)
{
thread12[i]=CreateThread(NULL, 0, Calculate, (LPVOID)i, 0, &thread_id[i+15]);
}
WaitForMultipleObjects(12, thread12, TRUE, INFINITE);
for (int i=0; i<(int)atr[0]; i++)
{
CloseHandle(thread12[i]);
}
time[6]=GetTickCount()-startTime;

maxTime=0;
for (int i=0; i<7; i++)
{
if (maxTime<time[i])
{
maxTime=time[i];
}
}

for (int i=0; i<7; i++)
{
coords[i]=(time[i]*700)/maxTime;
}

hwnd=CreateWindowEx(NULL, WINDOW_CLASS_NAME, szTitle, WS_VISIBLE|WS_OVERLAPPED, 0,0,1024,768, NULL, NULL, hInstance, NULL);
while( GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}
 
O

Odin_KG

Gwyllum
Насколько я помню, от того, что вы создадите в программе второй поток, второе ядро его выполнять не начнет. Т.е. все ваши потоки будут выполняться на одном ядре. А, чтобы подключить к потоку другое ядро, нужно использовать функцию: SetThreadAffinityMask

Дак вот не важно сколько потоков, но массив один и обратиться к нему параллельно не получится.
Я код не смотрел, но массив или не массив это не важно - лишь бы не было одновременного обращения нескольких потоков в один и тот же байт памяти. Причем читать одновременно можно - проблема только с записью. Т.е. если один поток работает с первым элементом массива, а второй со вторым, то конфликта нет.
 
G

Gwyllum

Gwyllum
Я код не смотрел, но массив или не массив это не важно - лишь бы не было одновременного обращения нескольких потоков в один и тот же байт памяти.
Нет) каждый поток обращается к своей части массива. За подсказку с функцией огромное вам спасибо! :D
 
Z

zeus

Суть моей программы - показать, что распараллеливание программы на двухъядерном процессоре способно увеличить скорость вычислений.
Ваша программа не сможет показать реальные параллельные вычисления))) почему? потому что вы забываете про 0й поток, в котором работает оконная процедура, т.е теоретически 1й поток у вас будет выполняться на одном ядре, а 2й будет делить время с 0м потоком, которые оба выполняются на втором ядре (или наоборот, не суть...)

Пишите консольные программы, в которых не нужно создавать окно, и выводите результаты в файл или на консоль )))
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">пример</div></div><div class="sp-body"><div class="sp-content">
C++:
#include <windows.h>
#define NUM 100

void calc(int *res)
{
...
} // calc

DWORD WINAPI thread(LPVOID val)
{
calc((int *)val);
return 0;
} // thread

int main(void)
{
int res[2][NUM];

HANDLE hThread = CreateThread(NULL, 0, thread, (LPVOID)res[0], 0, NULL);

calc(res[1]);

WaitForSengleObject(hThread, TRUE, INFINITE);
CloseHandle(hThread);

return 0;
} // main
 
G

Gwyllum

Ваша программа не сможет показать реальные параллельные вычисления))) почему? потому что вы забываете про 0й поток, в котором работает оконная процедура, т.е теоретически 1й поток у вас будет выполняться на одном ядре, а 2й будет делить время с 0м потоком, которые оба выполняются на втором ядре (или наоборот, не суть...)
Вы совершенно правы, но, если вычисляется сложная тригонометрическая формула, причем многократно, то время ее вычисления во много раз превышает время работы оконной процедуры. Таким образом, чем больше цикл,тем меньше будет влиять время выполнения оконной процедуры. Тем более, что сперва вычисляются все значения и только потом создается окно :D Но, все равно, спасибо большое, лучше и правда начать с консоли :)
 
G

Gwyllum

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

Обучение наступательной кибербезопасности в игровой форме. Начать игру!