Вам грустно? Одиноко? Устали ждать, когда закончится расчёт? Попробуйте многопоточность!:)
Рассмотрим это на примере двух скриптов. Первый вариант выполняет расчёт в основном потоке.
test1.m
a = rand(100,100); % массив случайных числе 100х100
tic; % засекаем начало
a^100; % возводим массив в степень 100
toc % засекаем окончание
Второй вариант создаёт 2 дополнительных потока и распределяет вычисления между ними.
test2.m
a = rand(100,100); % массив случайных числе 100х100
h1 = threadnew; % первый поток
h2 = threadnew; % второй поток
tic; % засекаем начало
threadstart(h1, 'power', 1, a, 50); % вычисляем a^50 в одном потоке
threadstart(h2, 'power', 1, a, 50); % вычисляем a^50 во втором потоке
res1 = threadvalue(h1); % результат для 1-го потока
res2 = threadvalue(h2); % результат для 2-го потока
res1*res2; % значение для сотой степени
threadfree(h1); % освобождаем 1-й поток
threadfree(h2); % освобождаем 2-й поток
tok % засекаем окончание
Теперь можно в FreeMat ввести "test1", и после нажатия Enter программа сообщит о длительности расчёта. В моём случае это 0,394 c. Затем аналогично вводим "test2". Время расчёта у меня составило 0,012 с. На самом деле во втором случае задействованы 3 потока: 2 дополнительных и 1 основной, который мы практически не использовали. Можно было бы создать один дополнительный поток и распределить вычисления между ним и основным потоком, но мои эксперименты показали, что при этом время понижается незначительно, видимо, он и без того нагружен. Отсюда можно сделать вывод, что для большого расчёта имеет смысл выделять отдельный поток.
Теперь рассмотрим, что необходимо для работы с многопоточностью в FreeMat. Новый поток создаётся функцией threadnew, которая возвращает его идентификатор. Дальнейшая работа с потоком осуществляется на основе этого идентификатора. Запуск расчёта выполняет функция
threadstart(поток, функция, результат, аргумент1, аргумент2, ...).
Здесь поток означает идентификатор, функция - имя функции (в кавычках), обрабатываемой в данном потоке, результат - число ожидаемых возвращаемых значений для функции (видимо, для каких-то специфических случаев). Далее идёт список аргументов, передаваемых выполняемой функции. В поток нельзя передать имя скрипта, это должна быть именно функция, встроенная или написанная пользователем. Все значения вычисляются локально, если необходима возможность обмена данными между потоками, соответствующие переменные должны быть объявлены с ключевым словом global, т.е. глобальными. В этом случае программа сама позаботится о том, чтобы исключить проблемы, связанные с совместным использованием данных несколькими потоками.
[рез1, рез2, ...] = threadval(поток, время ожидания)
считывает результат вычислений из потока с заданным идентификатором по окончании его работы. Если есть подозрение, что расчёт может уйти в бесконечный цикл, можно поставить максимальное время ожидания (в миллисекундах), при превышении которого будет возвращена ошибка.
По окончании работы с потоком его нужно освободить. Для этого служит функция threadfree(поток).
В FreeMat предусмотрено ещё несколько функций для работы с потоками. Однако рассмотренных выше для начала будет вполне достаточно.
Комментариев нет:
Отправить комментарий