gKit2 light
min_data.cpp
Go to the documentation of this file.
1 
3 
4 #include <cstddef>
5 #include <cstdio>
6 #include <cstdlib>
7 #include <ctime>
8 #include <vector>
9 #include <algorithm>
10 #include <chrono>
11 
12 #include "window.h"
13 
14 #include "vec.h"
15 #include "program.h"
16 #include "uniforms.h"
17 
18 
19 GLuint program= 0;
20 GLuint input_buffer= 0;
21 GLuint tmp_buffer= 0;
22 
23 std::vector<int> input;
24 
25 
26 const int logNmax= 26;
27 
28 int init( )
29 {
30  srand(time(nullptr));
31 
32  int o= rand() % 10000;
33  for(int i= 0; i < (1<<logNmax); i++)
34  input.push_back( o + rand() % 10000);
35 
36  glGenBuffers(1, &input_buffer);
37  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input_buffer);
38  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int) * input.size(), input.data(), GL_STATIC_READ);
39 
40  glGenBuffers(1, &tmp_buffer);
41  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, tmp_buffer);
42  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int) * input.size(), input.data(), GL_STREAM_READ);
43 
44 #define ATOMIC
45 
46 #ifndef ATOMIC
47  // version reduction globale
48  program= read_program("tutos/min_data.glsl");
49 #else
50  // version atomique
51  program= read_program("tutos/min_atomic.glsl");
52  program_print_errors(program);
53 #endif
54 
55  return 0;
56 }
57 
58 int quit( )
59 {
60  release_program(program);
61  glDeleteBuffers(1, &input_buffer);
62  glDeleteBuffers(1, &tmp_buffer);
63  return 0;
64 }
65 
66 
67 int main( int argc, char **argv )
68 {
69  // etape 1 : creer la fenetre
70  Window window= create_window(1024, 640, 4,3); // openGL version 4.3
71  if(window == NULL)
72  return 1;
73 
74  // etape 2 : creer un contexte opengl pour pouvoir dessiner
75  Context context= create_context(window);
76  if(context == NULL)
77  return 1;
78 
79  // etape 3 : creation des objets
80  if(init() < 0)
81  {
82  printf("[error] init failed.\n");
83  return 1;
84  }
85 
86  // taille max des groupes de shaders
87  GLint threads_max= 0;
88  glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &threads_max);
89  printf("threads max %d\n", threads_max);
90 
91  // dimension max des groupes de shaders
92  GLint size_max[3]= { };
93  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &size_max[0]);
94  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &size_max[1]);
95  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &size_max[2]);
96  printf("size max %d %d %d\n", size_max[0], size_max[1], size_max[2]);
97 
98  // nombre max de groupes de shaders
99  GLint groups_max[3]= { };
100  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &groups_max[0]);
101  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &groups_max[1]);
102  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &groups_max[2]);
103  printf("groups max %d %d %d\n", groups_max[0], groups_max[1], groups_max[2]);
104 
105  // taille de la memoire partagee
106  GLint size= 0;
107  glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &size);
108  printf("shared memory %dKb\n", size / 1024);
109  printf("\n");
110 
111 #ifndef ATOMIC
112  FILE *out= fopen("min_data.txt", "wt");
113 #else
114  FILE *out= fopen("min_atomic.txt", "wt");
115  //~ FILE *out= fopen("min_atomic_shared.txt", "wt");
116  //~ FILE *out= fopen("min_copy.txt", "wt");
117 #endif
118 
119  // pour N= 2, 4, 8, ... 2^n
120  for(int logN= 1; logN < logNmax; logN++)
121  {
122  int N= (1<<logN);
123 
124  // run
125  glUseProgram(program);
126 
127  // mesure le temps d'execution du dispatch
128  std::chrono::high_resolution_clock::time_point start= std::chrono::high_resolution_clock::now();
129 
130  #ifndef ATOMIC
131  // version reduction avec synchronisation externe
132  // 1ere etape
133  program_uniform(program, "N", (unsigned int) N);
134  program_uniform(program, "n", (unsigned int) 0);
135  glDispatchCompute((N+1023) / 1024, 1, 1);
136 
137  // etapes suivantes
138  program_uniform(program, "N", (unsigned int) 0);
139  for(int n= N/2; n > 1; n= n/2)
140  {
141  program_uniform(program, "n", (unsigned int) n);
142 
143  // attendre que les resultats temporaires sont dispos
144  glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
145 
146  //~ for(int i=0 ; i < 100; i++)
147  glDispatchCompute((n+1023) / 1024, 1, 1);
148  }
149 
150  #else
151  // version avec synchronisation "atomique"
152  program_uniform(program, "N", (unsigned int) N);
153  // un seul dispatch
154  for(int i=0 ; i < 100; i++)
155  {
156  glDispatchCompute((N+1023) / 1024, 1, 1);
157  //~ glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
158  }
159  #endif
160 
161  // recupere les resultats tmp
162  glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
163 
164  std::chrono::high_resolution_clock::time_point stop= std::chrono::high_resolution_clock::now();
165  long int gpu_time= std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count();
166 
167  std::vector<int> tmp(input.size(), 0);
168  glBindBuffer(GL_SHADER_STORAGE_BUFFER, tmp_buffer);
169  glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(int) * tmp.size(), tmp.data());
170 
171  printf("gpu min %d:", tmp[1]);
172  //~ printf(" %02dms %03dus\n", (int) (gpu_time / 1000000), (int) ((gpu_time / 1000) % 1000));
173  printf(" %03dus\n", (int) (gpu_time / 1000));
174 
175  {
176  // verification
177  std::chrono::high_resolution_clock::time_point start= std::chrono::high_resolution_clock::now();
178 
179  // version sequentielle cpu
180  int m= input[0];
181  for(int i= 1; i < N; i++)
182  m= std::min(m, input[i]);
183 
184  std::chrono::high_resolution_clock::time_point stop= std::chrono::high_resolution_clock::now();
185  long int cpu_time= std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count();
186 
187  printf("cpu min %d:", m);
188  printf(" %02dms %03dus\n", (int) (cpu_time / 1000000), (int) ((cpu_time / 1000) % 1000));
189 
190  // ecrire les temps d'execution dans le fichier
191  fprintf(out, "%d %f %f\n", N, gpu_time / 1000.f, cpu_time / 1000.f);
192 
193  printf("\n");
194  }
195  }
196  fclose(out);
197 
198  // etape 5 : nettoyage
199  quit();
200  release_context(context);
201  release_window(window);
202  return 0;
203 }
204 
Context create_context(Window window)
cree et configure un contexte opengl
Definition: window.cpp:356
void release_window(Window window)
destruction de la fenetre.
Definition: window.cpp:325
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition: text.cpp:140
Window create_window(const int w, const int h, const int major, const int minor, const int samples)
creation d'une fenetre pour l'application.
Definition: window.cpp:259
void release_context(Context context)
detruit le contexte openGL.
Definition: window.cpp:422
Point min(const Point &a, const Point &b)
renvoie la plus petite composante de chaque point. x, y, z= min(a.x, b.x), min(a.y,...
Definition: vec.cpp:30
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:204
void program_uniform(const GLuint program, const char *uniform, const std::vector< unsigned > &v)
affecte un tableau de valeurs a un uniform du shader program.
Definition: uniforms.cpp:94
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition: program.cpp:432
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:211
int init(std::vector< const char * > &options)
Definition: shader_kit.cpp:92