Friday, 20 July 2012

Accelero Twin Turbo II on a HIS Radeon 7850

Arctic Cooling Accelero Twin Turbo II on a HIS Radeon 7850.

For nearly six years I was doing fine with my desktop configuration: Intel Q6600 plus Nvidia GeForce 8800 GT 512. Last week, I decided it was time for an upgrade. After doing some research, I bought a Radeon 7850. As with all my hardware, I wanted to make it as silent as possible without breaking the bank. I was hoping I could use a Scythe Musashi, which did a fine job cooling my GeForce, but it turned out it was impossible to get in Poland. So I tried another well-known cooling hardware supplier, Arctic Cooling, and finally decided on an Accelero Twin Turbo II. I briefly considered the highly-rated Accelero Xtreme Plus, but it would have been too long for any Radeon 7850 card.

After reading the specification and manual of the Accelero Twin Turbo II, I knew I need to look for a version of Radeon 7850 that was as close to the reference design as possible, to avoid any compatibility issues. The main factor was also price, because I was going to throw away any custom-cooling solutions from the card producers anyway. I finally bought a HIS 7850 Fan 2GB DDR5 PIC-E DVI/HDMI/2xMini DP and it turned out to be a very good choice.

What follows is a tutorial on how to install the Accelero Twin Turbo II on a HIS Radeon 7850, based on my experiences. It's quite easy and takes little time, but because the glue on the heatsinks needs to harden (which takes at least 5 hours), I recommend starting in the evening and finishing the next morning.

I started with looking at the card and examining how to remove the stock cooler.

Original HIS Radeon 7850 card.

I noticed that the fan is connected to the board with a two-pin connector. This turned out to be important later, but for now you just need to remember to disconnect it before removing the stock cooler.

Two-pin connector on the HIS card.

I saw that the stock cooler was held in place with just four screws at the bottom of the card:

Four screws holding the stock cooler.

I removed the screws and put them away, as I didn't need them any more.

The card after removing four screws.


The stock cooler came off easily and I was left with the board:

Radeon 7850 card without cooler.

The main chipset was covered with old thermal compound, so I had to remove it with a paper towel (the new cooler comes with its own thermal compound).

Radeon 7850 without cooler, almost clean.

Then it was time for the Accelero Twin Turbo II package. It had two screws holding the bottom plastic cover, so I removed them:

Accelero Twin Turbo II bottom, with two screws holding the plastic cover.

After carefully removing the bottom (so that no parts fall out), the only thing left was the cooler itself:

Accelero Twin Turbo II bottom.

The bottom cover contained some heatsinks for RAM and other smaller chips, a power adapter (I didn't use it) and two backplates (also unnecessary for this configuration).

Contents of the bottom cover.

Proceeding according to the manual, I unscrewed the mounting plate:

Accelero Twin Turbo II with removed mounting plate.

I then tried the mounting plate on the Radeon and found that, on the mounting plate, I should use the holes labeled as "2" in the manual (they are the ones that are second closest to the center of the backplate). I also learned that I should use the 2.3mm spacers (black):

2.3mm spacers and adhesive tape.

Although the manual seems to suggests that the adhesive tape is double-sided, I only managed to get one side to stick, so I decided to glue it to the spacers:

Spacers with adhesive tape rings glued to them.

The next step was to screw the mounting plate to the Radeon. Four screws with appropriate washers were provided:

Screws for attaching the mounting plate to the card.

I put the spacers roughly where they should be on the mounting plate (they didn't stick to it):

Spacers on the mounting plate.

Because the height of Radeon's double-backplate was greater than that of the mounting plate, I found that the best position for screwing the mounting plate was close to the edge of the table, with the backplate hanging over the edge:

Attaching the mounting plate to the Radeon 7850.

While holding the card with my left hand, I inserted the screws with my right hand, fastening them a few rotations at a time, alternating between the screws, until all were tightened. After turning the board, it looked like this:

Radeon 7850 with the mounting plate of Accelero Twin Turbo II.

After that, it was time to install the small heatsinks. In the box there were several heatsinks of various shapes and sizes:


Small heatsinks of Accelero Twin Turbo II.

After a little trial-and-error, I managed to find a satisfying configuration that covered all important small chips on the card:

HIS Radeon 7850 with small heatsinks next to their designated positions.

Next, preparing the glue. Arctic Cooling suggests mixing the thermal glue in a small container. I thought the bottom right shaping in the cooler's plastic cover would do nicely:

Thermal glue components, plastic cover and mixing wand.

I carefully squeezed two parts of the glue into the container and mixed them for about four minutes until the substance was uniform, without any discolourings or lumps:

Mixing the thermal glue.

The manual states that after mixing, you have about 15 minutes to apply the glue. I found I didn't need that much time, but you don't have to hurry, as the glue takes a really long time to harden. Using the spatula, I covered all the small chips (NOT THE MAIN CHIP!) with glue. It's better to add very small amounts first and then add some more if the top is not fully covered in glue. In the end, I had 23 chips covered:

Small chips covered in glue: 4 large on the right, 2 small in the upper right corner, 4 large on top, 1 medium in the upper left corner, 12 small on the left. The middle (main) chip is NOT COVERED (although it looks like it is).

One by one, I started to put the small heatsinks into place. With each one, I pressed with my finger for about 10 seconds. I tried to position the heatsinks in such a way that they didn't touch the capacitors or any other board components. After positioning the heatsinks (15 of them), the card looked like this:

Radeon 7850 with small heatsinks attached.

Now it was time for the glue to harden. I decided to leave the card for the night, but I noticed there was something else I could do in the meantime. It turned out that the fan power connectors provided with the Accelero Twin Turbo II had three and four pins, whereas the card's power connector had two pins:

Accelero Twin Turbo II power connector with three pins.

HIS Radeon 7850 fan power connector with two pins.

These were clearly incompatible, but fortunately, it was a simple thing to fix. Notice the connector picture above. You can see three plastic protrusions positioned above three metal wires inside the connector. You can actually lift the protrusions with something thin (I used a safety pin, but a small screwdriver, a pin or a needle would also be OK) and gently pull out the metal wire:

Accelero Twin Turbo II fan power connector, disassembled.

I did the same with the connector from the original HIS cooler:

HIS fan power connector, disassembled.

The yellow wire, according to the pin assignment document, is used only as a control signal, so it's not mandatory. I inserted the remaining two wires into the two-pin connector exactly as they were before (with the protrusions visible, red on the bottom, black on the top):

Modified Accelero Twin Turbo II fan power connector.

I could still do one thing before letting the glue harden: choose the appropriate hole for the mounting plate. I measured the distance between the middle screw of the mounting plate and the bottom of the card. It was about 51mm:

The distance between the middle of the mounting plate and the bottom of the card.

According to the manual, this meant I should use the bottom (C) hole in the large heatsink. Sure enough, it looked like the whole cooler would easily fit above the PCI-E port line:

The distance between the bottom hole of the copper plate and the bottom of the cooler (33mm).

I then left the glue to dry and went to sleep. The next morning, I was ready for the final steps. First, I had to unscrew the mounting plate from the card. I couldn't use the edge of the table any more, because I didn't want to apply any pressure on the small heatsinks. I successfully used the old cooler cover as support, with the other end of the card "standing" on the backplate:

The card, prepared for unscrewing the mounting plate.

I carefully loosened the four screws until the mounting plate fell off from the bottom:

The card without the mounting plate.

I attached the mounting plate back to the cooler, using the lowest (C) holes and two screws:

The mounting plate attached to the cooler using the lowest possible holes.

Screwing the card back onto the mounting plate went exactly the same as the first time. I prepared the spacers...

Cooler with attached mounting plate and positioned spacers.

...and put the card on top, fastening the screws carefully, alternating between the screws until all held tight.

Fastening the screws of the mounting plate.

I carefully turned the card over. The work was almost complete:

The cooler attached to the card, power cable disconnected.

All that was left was to attach the power connector:

Attaching the power connector.

I wasn't satisfied with the length of the power cable, so I bound it with a rubber band. It wasn't beautiful, but it worked:

Power connector cable bound with a rubber band.

I took some time to admire the finished product:

Arctic Cooling Accelero Twin Turbo II attached to HIS Radeon 7850.

Here's how it looks when inserted into the slot on my motherboard:

HIS Radeon 7850 with Accelero Twin Turbo II cooling, on the motherboard.

Remember to connect the (single) PCI-E power connector to the card!

I took a little time to test the cooling performance of the card. After two rounds of default 3DMark 2011 benchmark, the temperature was 41 degrees Celsius, and the fan speed increased from 20% base to 24%:

Card status after two rounds of 3DMark 2011.

I was very satisfied with the noise level, so I didn't change any settings. You could, however, fix the fan speed at 20% with the AMD OverDrive tool. Or, you could start overclocking. For me, it's all about the silence. I recommend this cooler for anyone wanting to keep their computer quiet while still being able to play all the latest games.

Thursday, 2 December 2010

Operator "or" in Python's regular expressions is not greedy

This is what I learned today:

>>> import re
>>> re.findall(r'(a|ab)', 'ab')
['a']

I always thought that regular expressions in Python are greedy, but it seems I was mistaken. From the Python manual (quite hidden, but still explicitly written):

'|'

A|B, where A and B can be arbitrary REs, creates a regular expression that will match either A or B. An arbitrary number of REs can be separated by the '|' in this way. [...] As the target string is scanned, REs separated by '|' are tried from left to right. When one pattern completely matches, that branch is accepted. This means that once A matches, B will not be tested further, even if it would produce a longer overall match. In other words, the '|' operator is never greedy.

This means that reversing the order of items in parentheses produces the desired effect:

>>> re.findall(r'(ab|a)', 'ab')
['ab']

So if you have a list of strings and you want to find all occurrences of strings in this list in a (potentially large) text, you could easily create a regular expression from them and use it for searching:

regexp = re.compile(
ur'(%s)' % u'|'.join(re.escape(name) for name in names),
re.UNICODE | re.MULTILINE)

The problem is that if you have two names, e.g. "John" and "John Smith" and "John" comes before "John Smith" in the names list, "John Smith" will never be found, only "John".

To fix this, you can sort names in reverse order based on their length:

names.sort(key=lambda n: len(n), reverse=True)

This would work, but looks like a hack and anyway, regular expressions in the form (John|John Smith|...) could be improved. How about making a simple prefix tree and generating the regular expression from it? Like this one:

class PrefixTree(object):
'''
Prefix tree for generating optimal regular expressions.
'''
def __init__(self):
self.children = {}
self.terminal = False

def add(self, word):
if not word:
self.terminal = True
return
firstLetter, rest = word[0], word[1:]
if firstLetter not in self.children:
self.children[firstLetter] = PrefixTree()
self.children[firstLetter].add(rest)

def toRegex(self):
children = self._getRegexOfChildren()
if not self.terminal:
assert self.children
if self.terminal:
if children:
return '(%s)?' % children
else:
return ''
elif len(self.children) > 1:
return '(%s)' % children
else:
return children

def _getRegexOfChildren(self):
childkeys = sorted(self.children.keys())
return '|'.join(k + self.children[k].toRegex()
for k in childkeys)

Basic usage:

>>> pt = PrefixTree()
>>> pt.add('John')
>>> pt.add('John Smith')
>>> print pt.toRegex()
John( Smith)?

On a side note, regular expressions created from the prefix tree are twice as fast as the previous ones, created simply by joining all possible names.

Monday, 15 November 2010

iBooks "Dictionary not available for this language" fix

There is an irritating bug in the newest version of iBooks for iPhone (and probably also for iPad): if you try to use the built-in dictionary on English books that were converted (e.g. by Calibre) without the proper language set, you'll get an error:
Dictionary not available for this language
The culprit here is the metadata file of the ePub archive, content.opf. More specifically, it's an XML document that has a line corresponding to the language the book is supposed to be written in. The line should look like this:
<dc:language>en</dc:language>
But it often looks like this:
<dc:language>UND</dc:language>
I wrote a small script, epub-dict-fix, to batch-fix ePub files and assign a language (English by default) to them. You can get it from its Google Code homepage. I wrote it mainly for myself, but I hope it will be useful to someone else, too. Oh, and you need Python installed for it to work.

Tuesday, 12 October 2010

Subclassing frozenset

I encountered a strange "feature" of Python standard library a few days ago. I needed to subclass frozenset (an immutable set that is a part of Python standard library) to add some validation check on the contents in the constructor. My first approach looked like this:
def validate(iterable):
print 'validation:', iterable # complex validation here


class MyFrozenset(frozenset):

def __init__(self, iterable):
listed = list(iterable)
validate(listed)
frozenset.__init__(self, listed) # ***

if __name__ == '__main__':
fs = MyFrozenset([0, 1, 2, 3, 4])
print fs
Note that I took precautions and converted iterable to list to avoid consuming a generator before it reached frozenset's __init__. The code worked, but I received a strange warning:
validation: [0, 1, 2, 3, 4]
blog.py:17: DeprecationWarning: object.__init__() takes no parameters
frozenset.__init__(self, listed)
MyFrozenset([0, 1, 2, 3, 4])
It seemed as if frozenset didn't override __init__ at all! And true enough, removing the call to the parent constructor (marked with *** in the code) removed the warning while the code still worked!

I started wondering how it is possible for the set to be filled without passing the iterable to the parent. I made another check, but used a generator as argument instead:
def get_five():
for i in xrange(5):
yield i

if __name__ == '__main__':
fs = MyFrozenset(get_five())
print fs
Based on the previous warning, the results were not very surprising:
validation: []
MyFrozenset([0, 1, 2, 3, 4])
It seems that the generator had already been consumed before entering my __init__ method! I then remembered that there is another object initialization method you can call beside __init__: the __new__ method! I quickly checked Python help and found:
__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation.

It seems this is exactly what I was looking for! I quickly changed __init__ to __new__:
class ProperFrozenset(frozenset):

def __new__(cls, iterable):
listed = list(iterable)
validate(listed)
return frozenset.__new__(cls, listed)

if __name__ == '__main__':
fs = ProperFrozenset(get_five())
print fs
And it worked:
validation: [0, 1, 2, 3, 4]
ProperFrozenset([0, 1, 2, 3, 4])
I'm not sure why it's done this way in Python, but I guess it's for consistency: __init__ is a method that is called after an object has been created, so if the object is immutable, no method should be able to modify it. __new__, on the other hand, is called in the class context before the desired instance is created, so manipulation of arguments is still possible.

One mystery remains: if initialization of frozenset is done in its __new__ method, why do you still receive the iterable argument if you override __init__ and why not having an overridden __init__ doesn't raise a warning?

Sunday, 21 June 2009

Blog Name Change

The previous post wasn't exactly about Design Patterns or Python, so I decided to change the blog name. user_entitties is a name of a MySQL table that existed in a large project I was working on. It was there for about two years before someone noticed the funny spelling mistake. So, welcome to user_entitties! I hope you like it.

Show Photos of Two People in Picasa Web Albums

If you're a user of Picasa Web Albums, you probably know about the awesome feature of showing all photos that include a selected person. What you may not know is that, with a little tweak, you can show photos that include two (or more) people you chose. This is great e.g. for creating an album with only pictures of you and your friend, then creating a nice collage and making a great birthday gift!


So, how do you create such a filter? Notice that, when you view photos of one person, the URL of the webpage looks like this:



http://picasaweb.google.com/lh/view?uname=<username>&isOwner=true&subjectids=<long hash>#.

I don't think this is documented anywhere, but the subjectids parameter is actually a comma-separated list -- you just don't see it, because it has only one element. So, all you have to do is copy the <long hash> part from views of two (or more) different persons and combine it into one URL:



http://picasaweb.google.com/lh/view?uname=<username>&isOwner=true&subjectids=<long hash 1>,<long hash 2>#

And that's it! You can then easily download all photos in the album by opening its RSS feed (there's a small RSS link in the lower-right corner of the website) and downloading all photos, e.g. with FlashGot Firefox Extension. Here's how the header of three-people filter looks like:


Picasa Web Albums three persons filter

Monday, 15 October 2007

Global Quiz

For a break, let's make a quiz. Look at the following code and try to guess what the output will be:
queue = ['one']

def f():
print queue
queue = ['one', 'two']
print queue

f()

Select the text below for a correct answer:
Traceback (most recent call last):
File "quiz.py", line 8, in
f()
File "quiz.py", line 4, in f
print queue
UnboundLocalError: local variable 'queue' referenced before assignment

Surprised? I certainly was.
Well, what about this one:
queue = ['one']

def f():
print queue
queue.append('two')
print queue

f()

This time, the script behaves as expected:
['one']
['one', 'two']

To achieve the same result in the first example, a global statement must be added at the beginning of f():
queue = ['one']

def f():
global queue
print queue
queue = ['one', 'two']
print queue

f()

The most interesting thing is what happens now:
queue = ['one']

def f():
print queue

f()

We get:
['one']
without the global statement!
For the explanation of this strange behaviour, let's get back to the first example:
queue = ['one']

def f():
print queue
queue = ['one', 'two']
print queue

f()
It seems that f() treats the queue variable in the first print queue statement already as a local variable, although assignment to it is done no earlier than in the second line. This becomes reasonable if we realise that a Python method "knows" a list of its local variables before execution. This list is prepared when parsing the function definition and before the function is called. If you want to test it, you can write:
print f.func_code.co_varnames
before calling f() in the preceding examples. You'll notice that the output is () if we use the global statement or don't assign to queue inside the function, and (queue,) otherwise. An assignment to a variable which is not an argument of the function is treated as initialisation of a local variable -- hence the UnboundLocalError.

I encountered this error today while searching for a cause of a very strange bug. It would have been very hard to find if I hadn't run my favourite static code-checker tool: PyLint. I encourage everyone to use it, and it integrates well with PyDev, too. PyLint, when encounters the buggy code from the first example, throws a very nice warning:
W0621:  5:f: Redefining name 'queue' from outer scope (line 1)
...and everything becomes obvious.