пятница, 8 марта 2013 г.

scaling performance of libswscale versus OpenGL

There are many ways to scale an image. One can use provided libraries, or implement scaling via OpenGL pipeline. Latter choice looks preferred, as it uses hardware part which is desined to do suck tasks efficiently. But how fast OpenGL is? I've got following results on Celeron P4500 (it has integrated Ironlake video chip):

воскресенье, 24 февраля 2013 г.

redscale

I heard it is easier to look at red-colored interface. Don't know if it's true, or I just convinced myself, but it's really easier for me to read red text.
One can use
xcalib -invert -alter
to invert all output, but that don't cope with making it red. Fortunately, there is Color filter plugin for compiz that can alter colors both for whole desktop and for selected windows. One can use predefined present or create his own, by writing GL ARB fragment program. Here is one for reverse redscale:
!!ARBfp1.0
TEMP tex;
TEMP tex2;
TEX tex, fragment.texcoord[0], texture[0], RECT;
MOV tex2, {0, 0.0, 0.0, 1.0};
DP3 tex2.r, tex, {0.33333, 0.33333, 0.33333, 0};
ADD tex2.r, 1.0, -tex2.r;
MOV result.color, tex2.rbga;
END
and for redscale
!!ARBfp1.0
TEMP tex;
TEMP tex2;
TEX tex, fragment.texcoord[0], texture[0], RECT;
MOV tex2, {0, 0, 0, 0};
DP3 tex2.r, tex, {0.33333, 0.33333, 0.33333, 0};
MOV result.color, tex2.rbga;
END

Copy text to file, then select it in compiz config. Super-f activates shader for current window, Super-d for whole desktop.


пятница, 26 октября 2012 г.

dropbox and browser

dropbox on Debian launches x-www-browser to open its website. Unfortunately x-www-browser is set for whole system and user can't change it. But he can choose his own preferred browser and then invoke it by invoking sensible-browser. Fortunately dropbox first tries to execute x-www-browser from its installation, and as there is no such file, falls back to executing /usr/bin/x-www-browser. So issue can be solved by:

# ln -s /usr/bin/sensible-browser /var/lib/dropbox/.dropbox-dist/x-www-browser

One can set preferred browser by setting up evironment variable BROWSER (in .profile or .bashrc, for example).

суббота, 22 сентября 2012 г.

Add current directory to GTK+ file open dialog

Now GTK+ file open dialog offers no way to open file from current working directory. One can find recent documents, home directory or some other bookmarks. Quite frustrating when you know for sure where file you need is, but forced to traverse directory tree to current working directory.

Recently I found workaround. Solution is to add /proc/self/cwd as bookmark. Unfortunately path will be displayed as /proc/self/cwd, not actual cwd, but anyway, it works!

суббота, 21 июля 2012 г.

Simple maze solver with python and pyside

I'm practicing in Python, PySide and some algorithms. You can find a simple maze generator/solver below.





from PySide.QtCore import *
from PySide.QtGui import *
import sys
import random
 
class Maze(QWidget):
    def __init__(self, width, height, boxsize=7):
        QWidget.__init__(self)
 
        self.setMazeSize(width, height, boxsize)
        self.generateMazeDFS()
 
    def setMazeSize(self, width, height, boxsize):
        self.maze_width = width
        self.maze_height = height
        self.boxsize = boxsize
        self.setFixedSize(width * boxsize + 10, height * boxsize + 10)
 
    def generateMazeDumb(self, width=None, height=None, sparseness=None):
        if width is None: width = self.maze_width
        if height is None: height = self.maze_height
        if sparseness is None: sparseness = 2
 
        self.vwall = [[random.randint(0,sparseness) for x in range(0, width+1)] for y in range(0, height)]
        self.hwall = [[random.randint(0,sparseness) for x in range(0, width)] for y in range(0, height+1)]
        for x in range(0, width):
            self.hwall[0][x] = 0
            self.hwall[height][x] = 0
        for y in range(0, height):
            self.vwall[y][0] = 0
            self.vwall[y][width] = 0
 
    def generateMazeDFS(self, width=None, height=None, seed_point=None):
        if width is None: width = self.maze_width
        if height is None: height = self.maze_height
        if seed_point is None: seed_point = (random.randint(0, width-1), random.randint(0, height-1))
 
        self.vwall = [[0 for x in range(0, width+1)] for y in range(0, height)]
        self.hwall = [[0 for x in range(0, width)] for y in range(0, height+1)]
 
        maze = [[0 for x in range(0, self.maze_width)] for y in range(0, self.maze_height)]
 
        path = [seed_point]
        while True:
            possible_moves = []
            x, y = path[-1]
 
            if x > 0 and maze[y][x-1] == 0: possible_moves.append('left')
            if x < width-1 and maze[y][x+1] == 0: possible_moves.append('right')
            if y > 0 and maze[y-1][x] == 0: possible_moves.append('up')
            if y < height-1 and maze[y+1][x] == 0: possible_moves.append('down')
 
            if len(possible_moves) > 0:
                next_move = random.choice(possible_moves)
                maze[y][x] = 1
                if next_move == 'left':
                    self.vwall[y][x] = 1
                    path.append((x-1, y))
                    continue
                elif next_move == 'right':
                    self.vwall[y][x+1] = 1
                    path.append((x+1, y))
                    continue
                elif next_move == 'up':
                    self.hwall[y][x] = 1
                    path.append((x, y-1))
                    continue
                elif next_move == 'down':
                    self.hwall[y+1][x] = 1
                    path.append((x, y+1))
                    continue
            else:
                maze[y][x] = -1
                path.pop()
                if len(path) == 0:
                    break
 
    def paintEvent(self, event):
        qp = QPainter()
        qp.begin(self)
        qp.fillRect(0, 0, self.maze_width * self.boxsize + 10, self.maze_height * self.boxsize + 10, Qt.black)
 
        qp.translate(QPoint(5.5, 5.5))
        qp.setPen(Qt.white)
        b = self.boxsize
 
        # vertical walls
        y = 0
        for row in self.vwall:
            x = 0
            for w in row:
                if w == 0: qp.drawLine(x*b, y*b, x*b, (y+1)*b)
                x += 1
            y += 1
 
        # horizontal walls
        y = 0
        for row in self.hwall:
            x = 0
            for w in row:
                if w == 0: qp.drawLine(x*b, y*b, (x+1)*b, y*b)
                x += 1
            y += 1
 
        # path
        prev = None
        for point in self.path:
            x1 = point[0]
            y1 = point[1]
            if prev:
                x2 = prev[0]
                y2 = prev[1]
                qp.fillRect(b*min(x1,x2) + 2, b*min(y1,y2) + 2, b*abs(x1-x2)+b-4, b*abs(y1-y2)+b-4, Qt.green)
            else:
                qp.fillRect(x*b+2, y*b+2, b-4, b-4, Qt.green)
            prev = point
 
        # visited cells
        y = 0
        for row in self.maze:
            x = 0
            for m in row:
                if m == -1: qp.fillRect(x*b+2, y*b+2, b-3, b-3, Qt.gray)
                x += 1
            y += 1
 
        # target
        x, y = self.target
        qp.fillRect(x*b+2, y*b+2, b-3, b-3, Qt.red)
 
        # status
        if self.status:
            qp.setPen(Qt.white)
            qp.setFont(QFont("sans", 72, QFont.Normal))
            qp.drawText(QRect(0, 0, self.maze_width * b, self.maze_height * b),
                Qt.AlignCenter | Qt.AlignVCenter,
                self.status)
 
        qp.end()
 
    def step(self):
        self.step_num += 1
        x, y = self.path[-1]
 
        if (x, y) == self.target:
            self.status = "win"
            return False
 
        if self.step_select == 'random':
            order_list = ['u', 'r', 'd', 'l']
            random.shuffle(order_list)
        else:
            order_list = self.step_select
 
        for order in order_list:
            if order == 'u':
                # try step up
                if y > 0 and self.hwall[y][x] != 0 and self.maze[y-1][x] == 0:
                    self.path.append((x, y-1))
                    self.maze[y-1][x] = self.step_num
                    return True
            elif order == 'r':
                # try step right
                if x < self.maze_width-1 and self.vwall[y][x+1] != 0 and self.maze[y][x+1] == 0:
                    self.path.append((x+1, y))
                    self.maze[y][x+1] = self.step_num
                    return True
            elif order == 'd':
                # try step down
                if y < self.maze_height-1 and self.hwall[y+1][x] != 0 and self.maze[y+1][x] == 0:
                    self.path.append((x, y+1))
                    self.maze[y+1][x] = self.step_num
                    return True
            elif order == 'l':
                # try step left
                if x > 0 and self.vwall[y][x] != 0 and self.maze[y][x-1] == 0:
                    self.path.append((x-1, y))
                    self.maze[y][x-1] = self.step_num
                    return True
 
        # step back
        self.maze[y][x] = -1
        self.path.pop()
 
        if len(self.path) == 0:
            self.status = "loss"
            return False
 
        return True
 
    def init(self):
        self.maze = [[0 for x in range(0, self.maze_width)] for y in range(0, self.maze_height)]
        self.path = [(0, 0)]
        self.step_num = 1
        x, y = self.path[0]
        self.maze[y][x] = 1
        self.target = (self.maze_width-1, self.maze_height-1)
        self.status = False
 
 
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowTitle("Maze")
 
        self.maze = Maze(150, 80, 7)
 
        hbox = QHBoxLayout()
        hbox.setContentsMargins(0, 0, 10, 0)
        hbox.addWidget(self.maze)
        vbox = QVBoxLayout()
        vbox.setContentsMargins(0, 10, 0, 0)
        hbox.addLayout(vbox)
 
        self.le_w = QLineEdit("150")
        vbox.addWidget(QLabel("maze width:"))
        vbox.addWidget(self.le_w)
        self.le_h = QLineEdit("80")
        vbox.addWidget(QLabel("maze height:"))
        vbox.addWidget(self.le_h)
        self.le_b = QLineEdit("7")
        vbox.addWidget(QLabel("cell size:"))
        vbox.addWidget(self.le_b)
 
        self.dm_sparse = QLineEdit("2")
        vbox.addWidget(QLabel("Dumb mode sparseness:"))
        vbox.addWidget(self.dm_sparse)
 
        self.maze_type = QButtonGroup()
        rb_1 = QRadioButton("Dumb random maze")
        rb_1.setChecked(True)
        rb_2 = QRadioButton("DFS maze generator")
        self.maze_type.addButton(rb_1, 0)
        self.maze_type.addButton(rb_2, 1)
        vbox.addWidget(rb_1)
        vbox.addWidget(rb_2)
 
        self.btn_generate = QPushButton("Generate")
        self.btn_generate.clicked.connect(self.generateMaze)
        vbox.addWidget(self.btn_generate)
 
        self.step_order = QLineEdit("random")
        self.step_order.setPlaceholderText("step order")
        vbox.addWidget(self.step_order)
 
        self.btn_solve = QPushButton("Solve")
        self.btn_solve.clicked.connect(self.startSolving)
        vbox.addWidget(self.btn_solve)
 
        self.btn_stop = QPushButton("Stop")
        self.btn_stop.setEnabled(False)
        self.btn_stop.clicked.connect(self.stopSolving)
        vbox.addWidget(self.btn_stop)
 
        vbox.addStretch()
 
        proxy_widget = QWidget()
        proxy_widget.setLayout(hbox)
        self.setCentralWidget(proxy_widget)
 
        self.maze.init()
 
    def doStep(self):
        for k in range(0, 50):
            if not self.maze.step():
                self.timer.stop()
                self.stopSolving()
                break
        self.maze.repaint()
 
    def startSolving(self):
        self.btn_solve.setEnabled(False)
        self.btn_stop.setEnabled(True)
        self.btn_generate.setEnabled(False)
        self.maze.init()
 
        self.maze.step_select = self.step_order.text()
        if self.maze.step_select == '':
            self.maze.step_select = 'random'
 
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.doStep)
        self.timer.setInterval(50)
        self.timer.start()
 
    def stopSolving(self):
        self.btn_stop.setEnabled(False)
        self.btn_solve.setEnabled(True)
        self.btn_generate.setEnabled(True)
        self.timer.stop()
 
    def generateMaze(self):
        w = max(2, int(self.le_w.text()))
        h = max(2, int(self.le_h.text()))
        b = max(5, int(self.le_b.text()))
        sparseness = max(0, int(self.dm_sparse.text()))
 
        self.maze.setMazeSize(w, h, b)
        self.maze.init()
 
        if self.maze_type.checkedId() == 0:
            self.maze.generateMazeDumb(sparseness=sparseness)
        elif self.maze_type.checkedId() == 1:
            self.maze.generateMazeDFS()
        self.maze.repaint()
 
 
app = QApplication(sys.argv)
 
mw = MainWindow()
mw.show()
 
sys.exit(app.exec_())
 


пятница, 20 июля 2012 г.

CX_Find_Cell_With_Point and 3ddp (Fluent)

There is a function CX_Find_Cell_With_Point. It's not listed in official documentation but it works well when you need to find a cell which contains specified point. Otherwise one must use very slow dumb search or develop  some sofisticated search algorithms. But there is a glitch with its use. As it's undocumented, there is no guarantee that it even compiles.
`CX_Find_Cell_With_Point' does not work with double precision (3ddp) Fluent solver!
That's true for Fluent 6.2.16 on lnamd64 (at least). With 3ddp it always returns NULL.

And if you're here for example, here is a code:

#include "udf.h"
#include "surf.h"
#include "para.h"
 
void some_function()
{
    cell_t c;
    Thread *t;
    CX_Cell_Id cx_cell;
    CX_Cell_Id *cx_cell_ptr;
    real pt[3];
 
    CX_Start_ND_Point_Search(); /* call this before actual search */
                                /* perhaps it'll do some initializations */
    for (k = 0; k < 1000; k ++) {
        /* fill pt[3] with data */
        pt[0] = 0.0; pt[1] = 0.0; pt[2] = k / 1000.0;
 
        /* perform search */
        cx_cell_ptr = CX_Find_Cell_With_Point(pt);
        if (cx_cell_ptr) {   /* function can return NULL if no cell was found */
            cx_cell = *cx_cell_ptr;
            c = RP_CELL(&cx_cell);  /* get cell number */
            t = RP_THREAD(&cx_cell);  /* get cell thread */
 
            /* ... do your calculations ... */
 
        } else {
            /* no cell was found */
        }
 
    }
 
    /* It's a good practice to clean up */
    CX_End_ND_Point_Search();
}
 

пятница, 13 июля 2012 г.

another fluent 3ddp parallel benchmark

Another fluent 3ddp benchmark on Phenom II X6 1090T.
Unfortunatelly I don't remember what case was used.

procs; time per iteration; wall time; cpu time

smpi:
1 4.577 457.661 457.330
2 2.488 248.802 496.820
3 1.792 179.155 536.430
4 1.475 147.455 587.010
5 1.221 122.108 605.510
6 1.081 108.132 632.970
7 2.314 231.399 1202.540

nmpi:
5 1.569 156.866 669.320 nmpi
6 1.253 125.323 648.960 nmpi
7 3.235 323.487 1728.310 nmpi