Android x86, asmFish chess engine, amazing performance

First of all, this is info, that asmFish is running on Android x86 (Intel CPU) tablet Asus MeMO Pad 7 (ME176C), not recomendation for chess fans to buying some Intel tablet, but simply if you have it, you can try it, nothing more, nothing less. This solution is not officially supported and some people says, that it doesnt work for them and now I dont know all mandatory requirements to run asmFish on Android x86 devices.

I would like to ask everyone,  who will try it, please leave comment, if this is running or not on your Android x86 device (model, Android version). Thanks.

I have been trying to run asmFish chess engine on Android x86 tablet and it is running with amazing performance.

Android x86 tablet Asus MeMO Pad 7 (ME176C):

  • CPU, Intel Atom Z3745, 4 cores, 1.86GHz (64bit)
  • Android version (from Antutu benchmark) 5.0 (32bit)
    • Kernel version 3.10.20-x86_64_byt (64bit)
    • Pure Android from Asus, last updates, device is not rooted

Here are some simple benchmarks (Android Chess GUI DroidFish, 4 cores, hash table 256MB, without tablebases):

  • Stockfish, 2016-08-28, original version from DroidFish 1.62, 32bit, because this tablet has only 32bit Android:
    • Initial chess position (1. move): nps 750k
    • Some middlegame position (20. move): nps 850k
    • Some endgame position (50. move): nps 1150k
  • asmFish, linux version asmFish_2016-08-30_popcnt, 64bit:
    • Initial chess position (1. move): nps 1850k
    • Some middlegame position (20. move): nps  2100k
    • Some endgame position (50. move): nps 2700k

You can see, asmFish(64bit) has almost 2.5x higher speed than Stockfish(32bit) and this is amazing. You can always run latest version of asmFish, no need to wait for latest android version of Stockfish.

I was surprised that this 64bit linux version of asmFish is running on 32bit Android x86, but I think that it runs flawlessly, because:

  • tablet has 64bit CPU Intel
  • there is 64bit kernel
  • asmFish doesnt need any external libraries

I have found only one problem with asmFish, I had to lower SyzygyProbeLimit to 2, with higher limit asmFish is terminated.

How to add UCI engine to DroidFish (extract from DroidFish Help):

  • Copy one or more UCI engine binaries to the DroidFish/uci directory.
  • From the program menu, choose Manage Chess Engines and Select Chess Engine and select the engine to use.

I have been also made performance test between the same versions stockfish_16082809_32bit.exe and asmFishW_2016-08-30_popcnt.exe on Windows 10 Pro x64 and for two threads is difference about 60%.

Linux, Stockfish chess engine as remote service

Here is simple manual how to install and configure Stockfish chess engine as remote service on linux machine.

Install stockfish chess engine (this command is for Ubuntu machine)

sudo apt install stockfish

You can also simply download newer chess engine, for example from abrok.eu, or even compile your own version, source code you can download from Stockfish GitHub.

Install xinetd service on your linux machine (this command is for Ubuntu machine)

sudo apt install xinetd

Configure stockfish as remote service

Simply create file /etc/xinetd.d/stockfish, for example use vi editor:

sudo vi /etc/xinetd.d/stockfish

and insert this configuration:

# Stockfish remote engine
service stockfish
{
  disable = no
  server = /home/jerryg/Other/chess/engines/stockfish
  socket_type = stream
  protocol = tcp
  user = jerryg
  wait = no
  port = 3333
# only_from = localhost
}

change the item “server” to path, where is your stockfish engine and “user” to your username.

Now insert into file /etc/services this line:

stockfish 3333/tcp

Restart xinetd service and check, if stockfish remote service is working

Restart xinetd service:

sudo systemctl restart xinetd

Check status of xinetd service:

sudo systemctl status xinetd

you should see some output text, and there should not be something like “removing stockfish”, if you see this message then there is some problem.

Now simple check, if stockfish remote service is working:

telnet localhost 3333

you should see:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Stockfish 240816 64 POPCNT by T. Romstad, M. Costalba, J. Kiiski, G. Linscott

write uci, press Enter, you will see something like this:

option name Debug Log File type string default 
option name Contempt type spin default 0 min -100 max 100
option name Threads type spin default 1 min 1 max 128
option name Hash type spin default 16 min 1 max 1048576
option name Clear Hash type button
option name Ponder type check default false
option name MultiPV type spin default 1 min 1 max 500
option name Skill Level type spin default 20 min 0 max 20
option name Move Overhead type spin default 30 min 0 max 5000
option name Minimum Thinking Time type spin default 20 min 0 max 5000
option name Slow Mover type spin default 89 min 10 max 1000
option name nodestime type spin default 0 min 0 max 10000
option name UCI_Chess960 type check default false
option name SyzygyPath type string default <empty>
option name SyzygyProbeDepth type spin default 1 min 1 max 100
option name Syzygy50MoveRule type check default true
option name SyzygyProbeLimit type spin default 6 min 0 max 6
uciok

write quit to quit engine.

Now you have working Stockfish chess engine as remote service on your linux machine.

And finally connect to your Stockfish remote engine from your Chess program

Example 1, Android program DroidFish Chess:

Configure “Manage Chess Engines”, “Configure Network Engine”, “New Engine”, in the “Engine name” insert something like “Linux, Stockfish”, “Host name” is name or IP address your linux machine and “Port” is 3333, Press “OK” and thats all, now you can connect to your Linux Stockfish machine.

Example 2,  Windows program Arena Chess GUI:

Create new engine and in the “Detail panel”, in the field “Command Line” insert “c:\Program Files (x86)\Tools\PLINK.EXE” and in the field “Command Line Parameters” insert “-raw -P 3333 ip_address_or_name_of_linux_machine” and thats all.

PLINK.EXE download from Putty site.

Security issues arent concerned, if you want secure your Stockfish remote service, use something like Google 🙂

C code, palindrome algorithm, cost of conversion

Here is simple demonstration of cost of conversion from integer to string for palindrome algorithm.

Standard C code with conversion from integer to string:

#include <string.h>
#include <stdio.h>

#define PALINDROME_MAX 1000000

int is_palindrome(const char *s)
{
  unsigned int end = strlen(s) - 1;

  for (unsigned int i = 0; i <= end / 2; i++)
    if (s[i] != s[end - i])
      return 0;

  return 1;

}

int main()
{
  char s_number[8];
  unsigned int count = 0;

  for (unsigned int i = 0; i < PALINDROME_MAX; i++)
  {
    sprintf(s_number, "%d", i);
    if (is_palindrome(s_number))
      count++;
  }

  printf("Number of palindromes: %d\n", count);
  return 0;

}

Standard compilation and execution:

$ gcc is_palindrome_str.c -o is_palindrome_str -O3
$ time is_palindrome_str
Number of palindromes: 1999
real    0m0.173s
user    0m0.168s
sys    0m0.000s

So palindrome algorithm with conversion takes about 170ms.

And now, C code without conversion, this is my own code optimalized for max speed (which I was able to write 🙂 ):

#include <stdio.h>

#define PALINDROME_MAX 1000000

int is_palindrome(unsigned int num)
{
  // if num ends with 0, then is not palindrome
  // num 0 is palindrome
  if ((num % 10) || (num == 0))
  {
    static unsigned int num_prev;
    unsigned int rev = 0;

    // first half of num assigned to num
    // reversed second half of num assigned to rev
    while (num > rev)
    {
      rev = 10 * rev + num % 10;
      num_prev = num;
      num /= 10;
    }

    // if num has even number of digits, then compare rev == num
    // if num has odd number of digits, then compare rev == num_prev
    if ((rev == num) || (rev == num_prev))
      return 1;
  }

  return 0;

}

int main()
{
  unsigned int count = 0;

  for (unsigned int i = 0; i < PALINDROME_MAX; i++)
    if (is_palindrome(i))
      count++;

  printf("Number of palindromes: %d\n", count);

  return 0;

}

Again standard compilation and execution:

$ gcc is_palindrome_int.c -o is_palindrome_int -O3
$ time is_palindrome_int
Number of palindromes: 1999
real    0m0.016s
user    0m0.012s
sys    0m0.000s

A little bit surprising, this algorithm takes only 16ms.


So algorithm without conversion is 10x times quicker then algorithm with conversion.

If you are able write quicker palindrome algorithm, please dont hesitate an leave the code in the comment 🙂

Thanks for reading.

All codes was compiled and executed on Ubuntu 16.04 x64, gcc (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609, CPU AMD 2.2Ghz.