5

I have to print on screen 2^20 lines of integers under 1 second printf is not quick enough for there , are there any other easy to use alternatives for fast output?

Each line contains only 1 integer.

I require it for a competitive programming problem whose source code I have to submit to the judge.

Anmol Sood
  • 73
  • 1
  • 8
  • 2
    What do you mean by "print" - show them on screen, output them to a file, maybe even "really" print them out? Which OS? – Rob Mar 12 '14 at 12:28
  • Where do you want to print the numbers - console or what? You should to be more specific – Oleksandr Karaberov Mar 12 '14 at 12:29
  • 4
    @MarounMaroun & flyx 2^20 is roughly 1 million. If each line is 12 bytes it comes to 12 Mb/s. Could be done on a normal PC. – Klas Lindbäck Mar 12 '14 at 12:29
  • @Robert :- To show them on screen. Windows. – Anmol Sood Mar 12 '14 at 12:31
  • I already wrote 600MB of files with each possible entry with a length of 4, i guess i had 30mins for this on a slow computer but it was long time ago and i did it on java but there was a way. – ReeCube Mar 12 '14 at 12:33
  • 3
    What possible reason could you have to output a million lines of integers to the screen, anyway? Does your terminal have enough scrollback to read them? Do you have time to go look at them all? – Wooble Mar 12 '14 at 12:33
  • @AlexanderKaraberov :- console. – Anmol Sood Mar 12 '14 at 12:33
  • @Wooble :- I need that amount of output for a particular competitive programming problem. – Anmol Sood Mar 12 '14 at 12:35
  • @AnmolSood: ok... and are the judges of this particular competition going to look at a million integers on your console? This is beginning to sound like an XY Problem. – Wooble Mar 12 '14 at 12:37
  • Maybe he's building a test parcour for some witty OpenCV computer eye... I can't think of any other needs for this! – Rob Mar 12 '14 at 12:37
  • Are those random integers or are you counting up or something? – flyx Mar 12 '14 at 12:52
  • @flyx :- not random. ith number is some k*i where k can be determined in constant time for each iteration. – Anmol Sood Mar 12 '14 at 12:54
  • Another option you could try instead of using an alternative to `printf()` is to use a larger buffer for `printf()`. More buffer size normally means faster. Say you declare `char mybuffer[1000000]`, then you can change the buffer using `setvbuf(stdout, mybuffer, _IOFBF, sizeof(mybuffer))`. – RKG Mar 12 '14 at 15:24

4 Answers4

6

There is putchar and puts that you can try out.

If timing speed of the program is all that is required, you can print out to /dev/null (unix).

stefaanv
  • 14,072
  • 2
  • 31
  • 53
  • We once had a hexdump contest and that was one of the things we used to get more speed. – stefaanv Mar 12 '14 at 12:33
  • 1
    This might help a bit, but I don't think it's going to come close to meeting OP's request... the problem isn't just that `printf` is too slow, it's that terminals don't handle that kind of throughput. – Wooble Mar 12 '14 at 12:40
  • 1
    @Wooble It's for Online Judge so stdout will be redirected and not displayed on a physical terminal. – Klas Lindbäck Mar 12 '14 at 12:43
2

That's 4 MB of binary integer data. 5 MB if you count the newlines. If you like the data in binary, just write it out to wherever as binary values.

I'll assume you need formatting as well. The best way to do this then is to allocate a "huge" string which is big enough to handle everything, which in this case is 10+1 chars per integer. This means 11 MB. That is a reasonable memory requirement and definitely allocatable on a normal desktop system. Then, use sprintf to write the integer values out to the string:

#include <cstdio>
#include <iostream>
#include <string>

int main()
{
  std::string buffer(11534336, '\0');
  for (int i = 0; i < 1048576; ++i)
  {
    std::sprintf(&buffer[i * (10 + 1)], // take into account the newline
                 "%010d\n", i);
  }

  std::cout << buffer;
}

Note the effective formatting operation is very fast. The physical output to the console window will take some time on Windows, this is inherent to the Windows console and cannot be remedied. As an example, Coliru times out after 17872 entries, which I believe is 5 seconds. So unfortunately, printing to the screen at this speed is impossible using Standard C(++). You might be able to do it faster when you do everything on the GPU directly and display a surface/texture/image you create, but that can hardly be the point of the exercise.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
1

There are about three major bottlenecks in printf

  • parsing algorithm (must handle all kind of inputs/outputs)
  • base conversions (typically not optimized for your particular purpose)
  • I/O

The cure is

  • process multiple entries at time
  • process file i/o in blocks
  • finetune the base conversion for your specific problem

If your numbers are in order, you can have considerable increase of speed by processing multiple integers at a time; e.g.

char strings[10*6];
memcpy(strings, "10000\n10001\n10002\n10003\n10004\n", 30);
memcpy(strings + 30, "10005\n10006\n10007\n10008\n10009\n", 30);

fwrite(strings, 60, 1, stdout);

After each block of 10 integers are printed, one has to update the common part of the string, which can be done even with 1 x sprintf + 9x memcpy.

Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57
1

Expanding on what stefaanv mentioned about using putchar, this is a somewhat ugly C-style hack that should do the job fairly quickly. It makes use of the fact that ASCII decimal digits are 0x30 to 0x39:

inline void print_int(int val)
{
   char chars[10];   // Max int = 2147483647
   int digits = 0;
   if (val < 0)
   {
      putchar('-');
      val = -val;
   }

   do
   {
      chars[digits++] = ((val % 10) + 0x30);
      val /= 10;
   }while (val && digits < 10);

   while (digits>0)
   {
      putchar(chars[--digits]);
   }
   putchar('\n');
}
RKG
  • 150
  • 2
  • 8