source: proto/s2k/trunk/demo/strtoll/src/parallel_strtoll.cpp @ 4016

Last change on this file since 4016 was 4016, checked in by ksherdy, 5 years ago

Updated parallel IDISA/C++ strtoll.

File size: 6.8 KB
Line 
1/**
2 * Demo.
3 *
4 * Author:   Ken Herdy
5 *
6 * Usage:    parallel_strtoll <filename>
7 *
8 * Description:   
9 *
10 * Parallel ASCII to binary integer conversion demo, strtoll-like.
11 * Assumes LSD ASCII digit aligns to "high-end" of a 32-bit field.
12 *
13 * Given a 128 bit register this method
14 * converts 4 (32-bits) ASCII integers to 16-bit values.
15 *
16 **/
17
18/**
19 * Platform independent runtime support libraries and C++ libraries.
20 **/
21#include <simd-lib/bitblock.hpp>
22#include <simd-lib/carryQ.hpp>
23#include <simd-lib/pabloSupport.hpp>
24#include <simd-lib/bitblock_iterator.hpp>
25#include <simd-lib/transpose.hpp>
26#include <stdio.h>
27#include <stdlib.h>
28
29/**
30 * Platform independent type definitions.
31 **/
32typedef __m128i BitBlock;
33typedef BitBlock BytePack;
34typedef uint32_t scanblock_t;
35typedef uint32_t scanfield_t;
36
37/**
38 * Segment-at-a-time bufferd processing model parameters.
39 **/
40const int SCANBLOCK_SIZE   = (sizeof(scanblock_t) * 8);
41const int SCANFIELD_SIZE   = (sizeof(scanfield_t) * 8);
42// const int BLOCK_SIZE       =  (sizeof(BitBlock) * 8);                       
43const int SEGMENT_BLOCKS   = ((SCANBLOCK_SIZE * SCANFIELD_SIZE)/BLOCK_SIZE); 
44const int SEGMENT_SIZE     = (SEGMENT_BLOCKS * BLOCK_SIZE);
45const int CACHE_SIZE       = 32768;         
46const int BUFFER_SEGMENTS  = CACHE_SIZE / SEGMENT_SIZE;
47const int BUFFER_SIZE      = (BUFFER_SEGMENTS * SEGMENT_SIZE);
48
49BitBlock file_extent_mask(int size); 
50struct Basis_bits basis;
51
52/**
53 * Segment-at-a-time bufferd processing model parameters.
54 **/
55int bytes_read              = 0;
56int bytes_avail             = 0;
57
58int block                   = 0;
59int block_base              = 0; 
60
61int final_segment_size      = 0;
62int stream_pos              = 0;
63
64int main(int argc, char * argv[])
65{
66  if ((2 > argc) || (2 < argc)) { printf("Usage: %s <filename>\n", argv[0]); exit(-1); } 
67 
68  char * infilename = argv[argc-1]; 
69  FILE * istream;
70  if((istream = fopen(infilename, "rb")) == NULL ) { printf("fopen error"); exit( 1 ); } 
71
72  BytePack * Byte; 
73  BitBlock aligned_buffer[BUFFER_SIZE]; 
74  char * buffer = (char *) aligned_buffer;
75 
76  /**
77    * Segment-at-a-time processing.
78    **/
79  while(!feof(istream)) 
80  { 
81    /**
82     * Read Stream in BUFFER_SIZE byte chunks.
83     **/
84    bytes_read  = fread(buffer, 1, BUFFER_SIZE, istream);
85    bytes_avail = bytes_read;
86
87    if(feof(istream)) { bytes_avail--; }
88    if(ferror(istream)) { perror( "io error" ); exit(1); }
89 
90    /**
91     * Process full segments
92     **/
93    block_base = 0;
94    while (bytes_avail >= SEGMENT_SIZE) 
95    {
96     
97      for(block=0; block<SEGMENT_BLOCKS; block++, block_base+=BLOCK_SIZE) 
98      {
99        std::cerr << "Demo. Full blocks not implemented." << std::endl;
100                exit(1);
101      }
102
103      bytes_avail -= SEGMENT_SIZE;     
104      stream_pos += SEGMENT_SIZE;
105    }   
106   
107    /**
108     * Process the final partial segment as full blocks then partial blocks.
109     **/ 
110    block = 0;
111    final_segment_size = bytes_avail;
112
113    /**
114     * Process full blocks.
115     **/
116    while (bytes_avail >= BLOCK_SIZE) 
117    {
118      //transpose.do_block(&buffer[block_base], basis);
119      std::cerr << "Demo. Full blocks not implemented." << std::endl;
120      exit(1);     
121         
122      block_base += BLOCK_SIZE;
123      bytes_avail -= BLOCK_SIZE;
124      block++;
125    }
126
127    /**
128     * Process the final partial block.
129     **/
130    if(bytes_avail > 0) 
131    {
132                BitBlock FEM_mask = file_extent_mask(bytes_avail);
133                //transpose.do_final_block(&buffer[block_base], basis, FEM_mask);
134
135                // least significant digit '7' is 32-bit aligned.
136                BytePack * bytepacks = (BytePack *) "00031987000000000000000000000000000"; // (BytePack *) buffer;
137                BitBlock source_lo_128 = bytepacks[0];
138                BitBlock source_hi_128 = bytepacks[1];
139
140                // ! parallel extract (parallel gather)
141               
142                BitBlock r_3210         = hsimd<8>::packl(source_hi_128, source_lo_128);
143
144                // Reverse nybbles using inductive doubling and rotation,
145                // i.e. rotate least significant nybble (memory) to most significant nybble (register)
146                BitBlock rot_4          = simd_or(simd<8>::slli<4>(r_3210), simd<8>::srli<4>(r_3210));
147                BitBlock rot_8          = simd_or(simd<16>::slli<8>(rot_4), simd<16>::srli<8>(rot_4)); 
148                BitBlock rot_16         = simd_or(simd<32>::slli<16>(rot_8), simd<32>::srli<16>(rot_8)); 
149//              BitBlock rot_32         = simd_or(simd<64>::slli<32>(rot_16), simd<64>::srli<32>(rot_16)); 
150
151                // Parallel ASCII to binary integer conversion.
152                // Step 1 - Convert nybble pairs
153                BitBlock d_hi_4         = simd<8>::srli<4>(rot_16);
154                BitBlock lomask_8       = simd<8>::lomask();
155                BitBlock d_lo_4         = simd_and(rot_16, lomask_8);
156                BitBlock c_10           = simd<8>::constant<10>();
157                BitBlock t1_10          = simd<8>::mult(d_hi_4, c_10);
158                BitBlock t2_10          = simd<8>::add(t1_10, d_lo_4);
159
160                // Step 2 - Convert byte pairs
161                BitBlock d_hi_8         = simd<16>::srli<8>(t2_10);
162                BitBlock lomask_16      = simd<16>::lomask();
163                BitBlock d_lo_8         = simd_and(t2_10, lomask_16);
164                BitBlock c_100          = simd<16>::constant<100>();
165                BitBlock t1_100         = simd<16>::mult(d_hi_8, c_100);
166                BitBlock t2_100         = simd<16>::add(t1_100, d_lo_8);
167
168                // Step 3 - Convert double-byte pairs
169                BitBlock d_hi_16        = simd<32>::srli<16>(t2_100);
170                BitBlock lomask_32      = simd<32>::lomask();
171                BitBlock d_lo_16        = simd_and(t2_100, lomask_32);
172                BitBlock c_10000        = simd<32>::constant<10000>();
173                BitBlock t1_10000       = simd<32>::mult(d_hi_16, c_10000);
174                BitBlock t2_10000       = simd<32>::add(t1_10000, d_lo_16);
175
176                // BitBlock rslt        = hsimd<32>::packl(t2_10000, t2_10000);
177
178                // Step 4 - Convert quad-byte pairs // 32 bit integers
179/*
180                BitBlock d_hi_32                        = simd<64>::srli<32>(t2_10000);
181                BitBlock lomask_64                      = simd<64>::lomask();
182                BitBlock d_lo_32                        = simd_and(t2_10000, lomask_64);
183                BitBlock c_100000000            = simd<64>::constant<100000000>();
184                BitBlock t1_100000000s          = simd<64>::mult(d_hi_32, c_100000000);
185                BitBlock t2_100000000s          = simd<64>::add(t1_100000000s, d_lo_32);
186*/
187                // Step 5 - 64 integers ...
188
189                // Source
190                print_register<BytePack>("source_lo_128", source_lo_128);
191                print_register<BytePack>("source_hi_128", source_hi_128);
192
193                // Packl<8>
194                print_register<BytePack>("r_3210", r_3210);
195
196                // Rotate least significant nybble (memory) to most significant nybble (register)
197                print_register<BitBlock>("rot_4", rot_4);
198                print_register<BitBlock>("rot_8", rot_8);
199                print_register<BitBlock>("rot_16", rot_16);
200//              print_register<BitBlock>("rot_32", rot_32);
201
202                //! Write out to memory, results reside in the low 16 bits of each 32-bit field.
203
204                print_register<BytePack>("d_hi_4", d_hi_4);
205                print_register<BytePack>("d_lo_4", d_lo_4);
206                print_register<BytePack>("t2_10", t2_10);
207                print_register<BytePack>("t2_100", t2_100);
208                print_register<BytePack>("t2_10000", t2_10000);
209//              print_register<BytePack>("t2_100000000s", t2_100000000s);
210
211    }
212
213    stream_pos += final_segment_size;
214   
215  }
216
217  fclose(istream);
218
219  return 0; 
220}
221
222BitBlock file_extent_mask(int size) {
223  return bitblock::srl(simd<1>::constant<1>(), convert(BLOCK_SIZE-size));
224}
225
Note: See TracBrowser for help on using the repository browser.