пятница, 30 июля 2010 г.

OpenMP: простой пример параллелизации вычислений.

В Visual Studio 2005 необходимо включить поддержку OpenMP, после чего можно запустить такой простой пример (перемножение матриц):
#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QTime>
#include "omp.h"

int main(int argc, char *argv[])
{
 QCoreApplication a(argc, argv);

 int ii, jj, kk;
 const int dim = 1000;
 int * arr = new int[dim*dim];
 int * arr1 = new int[dim*dim];
 int * arr2 = new int[dim*dim];

 QTime time;
        time.start();

 for (ii = 0; ii < dim; ii++) {
  for (jj = 0; jj < dim; jj++) {
   for (kk = 0; kk < dim; kk++) {
    arr[ii, jj] = arr1[ii, kk] * arr2[kk, jj];
   }
  }
 }

 qDebug() << QString("Without OpenMP, time %1 sec").arg((double)time.elapsed()/1000);

 time.restart();

 #pragma omp parallel for shared(arr, arr1, arr2, dim) private(ii, jj, kk)
 for (ii = 0; ii < dim; ii++) {
  for (jj = 0; jj < dim; jj++) {
   for (kk = 0; kk < dim; kk++) {
    arr[ii, jj] += arr1[ii, kk] * arr2[kk, jj];
   }
  }
 }

 qDebug() << QString("With OpenMP, time %1 sec").arg((double)time.elapsed()/1000);

 delete [] arr;
 delete [] arr1;
 delete [] arr2;


 return a.exec();
}

Colored with dumpz.org


То есть перемножали матрицу без использования OMP и с использованием OMP. На выходе было (E7400 2.8GHZ):

"Without OpenMP, time 5.406 sec"
"With OpenMP, time 2.734 sec"

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

Тут можно почитать об этом чуть подробнее:
http://software.intel.com/ru-ru/articles/getting-started-with-openmp/

понедельник, 5 июля 2010 г.

Чтение с помощью STL

Очень интересный пример чтения файла с помощью STL:
http://easy-coding.blogspot.com/2009/02/stl.html

Любопытно скорость чтения последними двумя способами:

TEST(ReaderTest, istreambuf_iterator_tostring_short) {
  std::string v(
    (std::istreambuf_iterator<char>(
      std::ifstream(Env::testfile())
    )), 
    std::istreambuf_iterator<char>()
  );

  EXPECT_EQ(Env::testfile_sz(), v.length()); 
}


TEST(ReaderTest, istreambuf_iterator_tostring_short_auto_ptr) {
  std::string v(
    (std::istreambuf_iterator<char>(
      *(std::auto_ptr<std::ifstream>(
        new std::ifstream(Env::testfile())
      )).get()
    )), 
    std::istreambuf_iterator<char>()
  );

  EXPECT_EQ(Env::testfile_sz(), v.length()); 
}

Colored with dumpz.org


Если в VS2005 запускать без оптимизации, то каждый из этих двух тестов выполняется за 125 мс, а с оптимизацией - за 31 мс. То есть имеем четырехкратный прирост производительности.

четверг, 17 июня 2010 г.

STL: for_each и sort

В сети много примеров работы с STL, но часто в качестве шаблонного типа используется int или еще какой-то простой тип. Хотя довольно часто все не так тривиально и приходится хранить и сортировать достаточно сложные классы. Приведу небольшой пример. Допустим, у нас есть двухвалютный банковский счет с деньгами, причем сумма, понятно, зависит от текущего курса каждой из валют (доллар и евро). Чтобы упорядочить множество таких счетов, нужно учесть зависимость от текущего курса. Продемонстрируем это в коде:
#include <QtCore/QCoreApplication>
#include <QDebug>
#include <iostream>
#include <algorithm>
#include <list>
#include <math.h>

using namespace std;

void printInt(int numb);

//класс нашего банковского "кошелька"
class Wallet {
private:
  string owner;
  double eur;
  double usd;
public:
  //в конструкторе указываем дополнительные параметры
  //в данном случае это курсы валют относительно гривны
  Wallet(string owner, double usd, double eur) {
    this->owner = owner;
    this->eur = eur;
    this->usd = usd;
  };
  //как показывает практика, модификатор const тут необходим
  //(см. пояснения к коду)
  double getUsd() const { return usd; };
  double getEur() const { return eur; };
  void showInfo() {
    cout << "Wallet of " << owner << " contains a " << usd << " USD and " << eur << " EUR " << endl;
  };
};

void printWallet(Wallet & wallet) {
  wallet.showInfo();
};

//функтор для вывода информации
class WalletUahLess {
private:
  double uahToUsd;
  double uahToEur;
public:
  WalletUahLess(double uahToUsd, double uahToEur) {
    this->uahToUsd = uahToUsd;
    this->uahToEur = uahToEur;
  };
  //это обычный вариант сравнения двух "уошелкьков"
  bool operator() (Wallet & wallet1, Wallet & wallet2) {
    double uah1 = wallet1.getUsd()*uahToUsd + wallet1.getEur()*uahToEur;
    double uah2 = wallet2.getUsd()*uahToUsd + wallet2.getEur()*uahToEur;
    return uah1 < uah2;
  };
  //также бывает необходим и вариант с модификаторами const
  bool operator() (const Wallet & wallet1, const Wallet & wallet2) {
    double uah1 = wallet1.getUsd()*uahToUsd + wallet1.getEur()*uahToEur;
    double uah2 = wallet2.getUsd()*uahToUsd + wallet2.getEur()*uahToEur;
    return uah1 < uah2;
  };
};

int main(int argc, char *argv[])
{

  QCoreApplication a(argc, argv);

  vector<Wallet> wallets;

  //заполняем контейнер
  wallets.push_back(Wallet("Vasya", 960.50, 780.3));
  wallets.push_back(Wallet("Vova", 954.2, 789.56));
  wallets.push_back(Wallet("Piotr", 961.80, 792.67));
  wallets.push_back(Wallet("Ivan", 970.34, 760.50));
  wallets.push_back(Wallet("Sidor", 1090.76, 700.90));

  cout << endl << "before sort(): " << endl;
  for_each(wallets.begin(), wallets.end(), printWallet);

  //сортируем при одном курсе
  std::sort(wallets.begin(), wallets.end(), WalletUahLess(8.5, 9.6));
  cout << endl << "after sort() with WalletUahLess(8.5, 9.6): " << endl;
  for_each(wallets.begin(), wallets.end(), printWallet);

  //сортируем при другом курсе
  sort(wallets.begin(), wallets.end(), WalletUahLess(7.8, 11.5));
  cout << endl << "after sort() with WalletUahLess(7.8, 11.5): " << endl;
  for_each(wallets.begin(), wallets.end(), printWallet);

  return a.exec();
}

void printInt(int numb) {
  cout << numb << endl;
}

* This source code was highlighted with Source Code Highlighter.

На выходе консоли должно быть это:

before sort():
Wallet of Vasya contains a 960.5 USD and 780.3 EUR
Wallet of Vova contains a 954.2 USD and 789.56 EUR
Wallet of Piotr contains a 961.8 USD and 792.67 EUR
Wallet of Ivan contains a 970.34 USD and 760.5 EUR
Wallet of Sidor contains a 1090.76 USD and 700.9 EUR

after sort() with WalletUahLess(8.5, 9.6):
Wallet of Ivan contains a 970.34 USD and 760.5 EUR
Wallet of Vasya contains a 960.5 USD and 780.3 EUR
Wallet of Vova contains a 954.2 USD and 789.56 EUR
Wallet of Piotr contains a 961.8 USD and 792.67 EUR
Wallet of Sidor contains a 1090.76 USD and 700.9 EUR

after sort() with WalletUahLess(7.8, 11.5):
Wallet of Ivan contains a 970.34 USD and 760.5 EUR
Wallet of Vasya contains a 960.5 USD and 780.3 EUR
Wallet of Vova contains a 954.2 USD and 789.56 EUR
Wallet of Sidor contains a 1090.76 USD and 700.9 EUR
Wallet of Piotr contains a 961.8 USD and 792.67 EUR

Комментировать особо нечего, но стоит добавить, что использовать класс типа WalletUahLess вместо функции - это намного более гибкий и удобный способ сортировки, чем с помощью функции, т.к. позволяет задать дополнительные параметры - в данном случае различные курсы валют, не создавая при этом новый класс или функтор для сравнения.
В процессе выяснилась интересная вещь: на VS-2005 все замечательно работало, а на QT4 вдруг оказалось, что не хватает функции сравнения, где оба сравниваемых аргумента объявлены как const. После добавления перегруженной версии оператора (operator() (const Wallet, const Wallet &)) с константными объектами компилятор сообщил, что функции getUsd() и getEur() не могут вызываться в константном объекте, так как они сами не константные. После того, как они были объявлены константными, все заработало. Из чего можно сделать вывод, что реализации STL в разных компиляторах могут отличаться.
Также оказалось, что функция qSort() из библиоеки Qt работает так же, как и stl::sort() с объектами std::vector и не требует функции с const-параметрами.

вторник, 30 марта 2010 г.

Python

Питон - очень удобный и мощный скриптовый язык. Имеет красивый, легко читаемый синтаксис (это немаловажно).
Как всегда, хорошая статья на ibm.com:
http://www.ibm.com/developerworks/ru/library/l-python/?S_TACT=105AGX99&S_CMP=GR01

суббота, 27 марта 2010 г.

Обзор ЖК-мониторов

Обзор наиболее популярных технологий ЖК-мониторов (TN+Film, MVA, PVA, IPS), очень хорошая статья:
http://www.fcenter.ru/online.shtml?articles/hardware/monitors/10071

Детальный обзор мониторов Samsung F2080 и F2380:
http://www.fcenter.ru/online.shtml?articles/hardware/monitors/27237

Есть и куча обзоров других мониторов:
http://www.fcenter.ru/online.shtml?articles/hardware/monitors/14042

среда, 24 марта 2010 г.

Регулярные выражения

Регулярные выражения (Pattern, Matcher):
String input = "Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord.";
Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)+");
Matcher matcher = pattern.matcher(input);

while (matcher.find()) {
  System.out.println("Found this wiki word: " + matcher.group());
}


* This source code was highlighted with Source Code Highlighter.

На выходе должны быть:
Found this wiki word: WikiWord
Found this wiki word: AnotherWikiWord
Found this wiki word: SomeWikiWord
http://www.ibm.com/developerworks/ru/edu/j-intermed/section5.html