Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm для Windows/Dos > параллелизация


Автор: turbanoff 22.5.2009, 15:04
значит так, есть у нас в университете такой предмет "Параллельные алгоритмы".
на зачет программа:
"Реализуйте линейный конгруэнтный генератор псевдослучайных чисел, распараллелив его на два процессора методом блочного разбиения. В качестве модуля генератора m сгенерируйте простое трехзначное число. На базе полученного генератора псевдослучайных чисел реализуйте поточное шифрование, путем побитового «ИСКЛЮЧАЮЩЕГО ИЛИ» псевдослучайной последовательности с исходным текстом. Процесс шифрования также необходимо распараллелить на два процессора."

главная "оценка" программы состоит в оценке времени её работы на 1-м и 2-х процессорах соответственно. (Нужно показать что на 2-х как-никак быстрее)

ну закодил вот я (fasm):
Код

format PE console
entry start

include 'include\win32a.inc'
n = 02000000h    ;4-х байтовых слов на каждый поток

section '.data' data readable writeable


hOut dd ?
tH1 dd ?
ns dd ?
countbytes dd ?


a dd 69069
c dd 5

stime dd ?
etime dd ?

tID1 dd ?

first_param:
    x0        dd 3
    nfirst  dd n
    fmem    dd filedump

second_param:
    xn        dd ?
    nsecond dd n
    smem    dd filedump + n

;cline    dd ?
soutime db 12 dup (' ')
fstring db "%u",0

inpath db "in.txt",0
inhandle dd ?
outpath db "out.txt",0
outhandle dd ?
filedump dd 2*n dup ?



section '.text' code readable executable
start:         
    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov [hOut],eax
    
    invoke CreateFile, inpath, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
    cmp eax, INVALID_HANDLE_VALUE
    je @F
        ;считываем 2*n 4-х байтовых слова из файла
        mov [inhandle], eax
        invoke ReadFile, eax, filedump, 4*2*n, countbytes, NULL
        invoke CloseHandle, [inhandle]
    @@:
    invoke GetCommandLine
    ;mov [cline], eax
    
    mov edi, eax
    xor al, al
    mov ecx, 261
    repne scasb    ;ищем конец командной строки
    
    mov bl, [edi-2]    ;последний байт в bl
    
        invoke GetTickCount        ; засекаем время
        mov [stime], eax
        
    cmp bl, '1'
    jne @F
        mov    [soutime],'1'

        
        ;один поток
        mov [nfirst], n*2
        push first_param
        call OurThread
        jmp endprogram
    
    @@:
        ;2 потока
        
        mov    [soutime],'2'
        
        mov eax, [a]
        mov ecx, n
        ;;;;
        ;;;call exponent
        
        mov edi, 1
        stexp:
                jecxz endexp
                test ecx, 1
                jz @F
                        xchg eax, edi
                        mul edi
                        xchg edi, eax
                @@:
                mul eax
                shr ecx, 1
                jmp stexp
        endexp:
        mov eax, edi
        
        ;;
        mul [x0]
        push eax    ; a^n * u[0]
        
        mov ebx, [a]
        mov ecx, n-1
        ;call magicFunc
        mov eax, 1  ; summ-a
        @@:
            mul ebx
            inc eax
            loop @B
            
        mul [c]
        pop ebx
        add eax,ebx
        mov [xn],eax    ; сохранили n-й член последовательности
            
        invoke CreateThread, 0, 0, OurThread, first_param, 0, tID1
        mov [tH1], eax
        
        push second_param
        call OurThread
        
        invoke WaitForSingleObject, eax, 0FFh
        
    
endprogram:    
    invoke GetTickCount
    mov [etime], eax
    sub eax,[stime]
    invoke wsprintf , soutime+2, fstring, eax
    add esp, 12
    invoke WriteConsole,[hOut],soutime,12,ns,NULL
    
    invoke CreateFile, outpath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
    cmp    eax, INVALID_HANDLE_VALUE
    je @F
        mov [outhandle], eax
        invoke WriteFile, eax, filedump, [countbytes], countbytes, NULL
        invoke CloseHandle, [outhandle]
    @@:
    invoke ExitProcess,0

    ;ПОТОКОВАЯ ФУНКЦИЯ
proc OurThread parametr
    mov eax, [parametr]
    
    mov edi, [eax+8]    ; куда записывать результат
    mov ecx, [eax+4]    ; количество
    mov eax, [eax]        ; зерно
    
    @@:
        mul [a]
        add eax, [c]
        
        xor [edi],eax
        add edi, 4
        ;stosd
        
        loop @B
    ret
endp
    
section '.idata' import data readable

  library kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'
     include 'INCLUDE\api\kernel32.inc'
     include 'INCLUDE\api\USER32.INC'


в общем запускаю я её с аргументами "1" или "2".
программа правильно определяет ск-ка потоков надо запустить (0 или 1 соответственно), запускает и считает случайные числа и даже шифрует/дешифрует правильно

но одна проблема: никакого прироста в скорости при запуске на 2-х потоках не ощущается, даже наоброт.
даже не знаю что делать  smile 
ка бы так её изменить чтобы и задачу она выполняла правильно и время работы на 2-х было бы хотя на чуток больше чем на 1-м. 

Автор: airyashov 24.5.2009, 02:03
Как вариант написать на Си и проверить, если время будет попробую реализовать

Автор: W4FhLF 24.5.2009, 08:30
Основное время уходит на обращение к памяти и винту(чем больше обращений, тем медленнее работает ессно), поэтому распараллеливание здесь до фени. 

Автор: turbanoff 25.5.2009, 13:53
Цитата(W4FhLF @ 24.5.2009,  08:30)
Основное время уходит на обращение к памяти и винту(чем больше обращений, тем медленнее работает ессно), поэтому распараллеливание здесь до фени.

это я понимаю, задача не в этом, именно распарралелить генератор, и засечь именно это время.
на си - не вариант.

Автор: airyashov 26.5.2009, 23:10
передумал

Автор: ksili 27.5.2009, 06:24
Если проц одноядерный и без HyperThreaing, то два потока скорее всего будут работать медленнее. Потестируй на двухядерном компе.

Автор: turbanoff 2.6.2009, 20:44
Цитата(ksili @ 27.5.2009,  06:24)
Если проц одноядерный и без HyperThreaing, то два потока скорее всего будут работать медленнее. Потестируй на двухядерном компе.

собственно и тестировал на 2-х ядерном, главна проблема - нахождение зерна для 2-го потока.

формула вот такая U(n) = a^n * U(0) + c*(a^n - 1)/(a - 1) mod M

M = 2^32;

вычисление степени  a^n я сделал "эффктивно", осталась проблема с (a^n - 1)/(a - 1) mod M, как по мне именно это вычисление занимает меного времени

Автор: ksili 3.6.2009, 04:49
mod M тоже можно сделать эффективно - с помощью сдвигов, если M - степень двойки

Автор: Mikl_ 3.6.2009, 05:11
Цитата(ksili )
mod M тоже можно сделать эффективно - с помощью сдвигов, если M - степень двойки 
Не болтайте ерундой! если M - степень двойки, то x mod M = x AND (M-1) и где здесь сдвигиsmile 

Автор: ksili 3.6.2009, 05:32
точно, чё-то я ещё не проснулся. Хотя сдвигами тоже можно было сделать, но наверно немного менее эффективно:
x mod (2^y) = (x << y) >> y;

А вообще если программа 32-битная, то надо ещё посмотреть, есть ли там вообще смысл вычислять остаток от деления на 2^32.

Автор: Mikl_ 3.6.2009, 08:41
Цитата
ksili написалХотя сдвигами тоже можно было сделать, но наверно немного менее эффективно:
x mod (2^y) = (x << y) >> y;
Наверное, если x 32-разрядное, тогда x mod (2^y) = (x << (32-y)) >> (32-y)  smile 

Автор: turbanoff 7.6.2009, 13:07
Цитата(ksili @ 3.6.2009,  04:49)
mod M тоже можно сделать эффективно - с помощью сдвигов, если M - степень двойки

проблема не в вычислении модулю, а в нахождении
(a^n - 1)/(a - 1) mod M

если пользоваться формулой, которую я использовал

(a^n - 1)/(a - 1)  = a^0 + a^1 + a^2 + ... + a^(n-2) + a^(n-1)

то прироста скорости по сравнению с обычный линейным конгруэнтным генератором почти нет - теже самые N шагов

Автор: Mikl_ 8.6.2009, 05:59
turbanoff
"Реализуйте линейный конгруэнтный генератор псевдослучайных чисел, распараллелив его на два процессора методом блочного разбиения. В качестве модуля генератора m сгенерируйте простое трехзначное число. На базе полученного генератора псевдослучайных чисел реализуйте поточное шифрование, путем побитового «ИСКЛЮЧАЮЩЕГО ИЛИ» псевдослучайной последовательности с исходным текстом. Процесс шифрования также необходимо распараллелить на два процессора."

"проблема не в вычислении модулю, а в нахождении: (a^n - 1)/(a - 1) mod M"

"нашел обсуждение этого вопроса и решение в книжке: "Алгоритмические трюки для программистов" Генри Уоррен
PS. всем советую" smile  


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)