/normxcorr/trunk

To get this branch, use:
bzr branch http://suren.me/webbzr/normxcorr/trunk

« back to all changes in this revision

Viewing changes to dict_hw/src/dict_hw.cu

  • Committer: Suren A. Chilingaryan
  • Date: 2010-04-25 04:39:54 UTC
  • Revision ID: csa@dside.dyndns.org-20100425043954-v7xm2bzohickyl9z
Multi-GPU support

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#include "normxcorr_hw.h"
17
17
#include "normxcorr_hw.cu.h"
18
18
 
19
 
#define MAX_DEVICES 16
 
19
 
 
20
#define CHECK_ERROR(err) \
 
21
    for (icp = 0; icp < ncp; icp += per_device) { \
 
22
        int i = icp / per_device; \
 
23
        ProcessingState ps = ctx->pstates[i]; \
 
24
        if (ps->status) { \
 
25
            err = ps->status; \
 
26
            break; \
 
27
        } \
 
28
    } \
 
29
 
 
30
 
20
31
 
21
32
static int device_number = 0;
 
33
#ifdef DICT_SUPPORT_THREADS
22
34
static int devices[MAX_DEVICES];
 
35
#endif /* DICT_SUPPORT_THREADS */
23
36
static size_t device_memory = 2147483648;
24
37
 
25
38
#ifdef DICT_HW_MEASURE_TIMINGS
46
59
            memory = deviceProp.totalGlobalMem;
47
60
            if (memory > 268435455) {   // 256 MB
48
61
                if (memory < device_memory) device_memory = memory;
 
62
#ifdef DICT_SUPPORT_THREADS
49
63
                devices[device_number++] = i;
 
64
#else /* DICT_SUPPORT_THREADS */
 
65
                device_number = 1;
 
66
#endif /* DICT_SUPPORT_THREADS */
50
67
            }
51
68
        }
52
69
    }
59
76
    return device_number;
60
77
}
61
78
 
 
79
static void dictFree(DICTContext ctx) {
 
80
    if (ctx->image_buf) {
 
81
        dictImageFree(ctx);
 
82
    }
 
83
 
 
84
    if (ctx->base_image) free(ctx->base_image);
 
85
    if (ctx->points) cudaFreeHost(ctx->points);
 
86
 
 
87
    memset(ctx, 0, ((char*)&(ctx->matlab_mode)) - ((char*)ctx));
 
88
}
 
89
 
 
90
#ifdef DICT_SUPPORT_THREADS
 
91
static int dictInitThread(HWThread thr, void *hwctx, int device_id, void *data) {
 
92
    cudaError cuda_err;
 
93
 
 
94
    cuda_err = cudaSetDevice(devices[device_id]);
 
95
    if (cuda_err) {
 
96
        reportError("Failed to associate cuda device");
 
97
    }
 
98
        
 
99
    return 0;
 
100
}
 
101
#endif /* DICT_SUPPORT_THREADS */
 
102
 
62
103
DICTContext dictCreateContext() {
 
104
    int i;
 
105
    
63
106
#ifdef DICT_HW_MEASURE_TIMINGS
64
107
    struct timeval tv1, tv2;
65
108
#endif /* DICT_HW_MEASURE_TIMINGS */
71
114
#ifdef DICT_HW_MEASURE_TIMINGS
72
115
    gettimeofday(&tv1, NULL);
73
116
#endif /* DICT_HW_MEASURE_TIMINGS */
74
 
 
75
 
    TProcessingState *pstate = pstateInit();
 
117
    
 
118
    DICTContext ctx = (DICTContext)malloc(sizeof(TDICTContext));
 
119
    if (!ctx) return ctx;
 
120
 
 
121
    memset(ctx, 0, sizeof(TDICTContext));
 
122
    
 
123
    ProcessingState *pstates = (ProcessingState*)malloc(device_number * sizeof(ProcessingState));
 
124
    if (!pstates) {
 
125
        dictDestroyContext(ctx);
 
126
        return NULL;
 
127
    }
 
128
    
 
129
    memset(pstates, 0, device_number * sizeof(ProcessingState));
 
130
    ctx->pstates = pstates;
 
131
 
 
132
    for (i = 0; i < device_number; i++) {
 
133
        TProcessingState *pstate = pstateInit();
 
134
        if (!pstate) {
 
135
            dictDestroyContext(ctx);
 
136
            return NULL;
 
137
        }
 
138
        
 
139
        ctx->pstates[i] = pstate;
 
140
    }
 
141
 
 
142
#ifdef DICT_SUPPORT_THREADS
 
143
    ctx->sched = hw_sched_create(device_number);
 
144
    if (!ctx->sched) {
 
145
        dictDestroyContext(ctx);
 
146
        return NULL;
 
147
    }
 
148
 
 
149
    hw_sched_schedule_task(ctx->sched, ctx, dictInitThread);
 
150
    hw_sched_wait_task(ctx->sched);
 
151
#endif /* DICT_SUPPORT_THREADS */
76
152
 
77
153
#ifdef DICT_HW_MEASURE_TIMINGS
78
 
    if (pstate) {
79
 
        gettimeofday(&tv2, NULL);
80
 
        pstate->time[0] = hardware_detection_time;
81
 
        pstate->time[1] = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
82
 
    }
 
154
    gettimeofday(&tv2, NULL);
 
155
    ctx->time[0] = hardware_detection_time;
 
156
    ctx->time[1] = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
83
157
#endif /* DICT_HW_MEASURE_TIMINGS */
84
158
 
85
 
    return pstate;
 
159
    return ctx;
86
160
}
87
161
 
88
162
void dictDestroyContext(DICTContext ctx) {
 
163
    int i;
 
164
    
89
165
#ifdef DICT_HW_MEASURE_TIMINGS
90
166
    int time;
91
167
    struct timeval tv1, tv2;
92
168
 
93
 
    int init_time = ctx->time[0]+ctx->time[1]+ctx->time[2]+ctx->time[3]+ctx->time[12]+ctx->time[13];
 
169
    int init_time = ctx->time[0]+ctx->time[1]+ctx->time[2]+ctx->time[3]+ctx->time[12]+ctx->time[13]+ctx->time[17];
94
170
    int load_time = ctx->time[14] + ctx->time[15];
95
171
    int process_time = ctx->time[5];
96
172
    
97
 
    if (ctx->use_cache) init_time += ctx->time[6];
98
 
    
99
173
    reportMessage("");
100
174
    reportMessage("Library timings");
101
175
    reportMessage("---------------");
107
181
    print_timing("  Setting Current Points", ctx->time[3]);
108
182
    print_timing("  Loading Template Image", ctx->time[12]);
109
183
    print_timing("  Reducting Template Image", ctx->time[13]);
110
 
    if (ctx->use_cache) {
111
 
        print_timing("  Processing Template Image", ctx->time[6]);
112
 
    }
 
184
    print_timing("  Processing Template Image", ctx->time[17]);
 
185
 
113
186
    print_timing("Loading Images", load_time);
114
187
    print_timing("  Load", ctx->time[14]);
115
188
    print_timing("  Reduction", ctx->time[15]);
116
189
    print_timing("Processing Images", process_time);
117
 
    if (!ctx->use_cache) {
 
190
 
 
191
    if (!ctx->use_threads) {
118
192
        print_timing("  Processing Template Image", ctx->time[6]);
 
193
        print_timing("  Copy Image   ", ctx->time[4]);
 
194
        print_timing("  Load Fragment", ctx->time[7]);
 
195
        print_timing("  Preprocessing", ctx->time[8]);
 
196
        print_timing("  FFT", ctx->time[9]);
 
197
        print_timing("  Postprocessing", ctx->time[10]);
119
198
    }
120
 
    print_timing("  Copy Image   ", ctx->time[4]);
121
 
    print_timing("  Load Fragment", ctx->time[7]);
122
 
    print_timing("  Preprocessing", ctx->time[8]);
123
 
    print_timing("  FFT", ctx->time[9]);
124
 
    print_timing("  Postprocessing", ctx->time[10]);
125
199
    print_timing("Waiting Result", ctx->time[16]);
126
200
 
127
201
    gettimeofday(&tv1, NULL);
128
202
#endif /* DICT_HW_MEASURE_TIMINGS */
129
 
    pstateFree(ctx);
 
203
 
 
204
    dictFree(ctx);
 
205
 
 
206
#ifdef DICT_SUPPORT_THREADS
 
207
    if (ctx->sched) hw_sched_destroy(ctx->sched);
 
208
#endif /* DICT_SUPPORT_THREADS */
 
209
 
 
210
    if (ctx->pstates) {
 
211
        for (i = device_number; i > 0; --i) {
 
212
            if (ctx->pstates[i - 1]) pstateFree(ctx->pstates[i - 1]);
 
213
        }
 
214
        free(ctx->pstates);
 
215
    }
 
216
    free(ctx);
 
217
 
130
218
#ifdef DICT_HW_MEASURE_TIMINGS
131
219
    gettimeofday(&tv2, NULL);
132
220
    time = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
139
227
    return reportSet(error_reporter, message_writer);
140
228
}
141
229
 
142
 
int dictSetup(DICTContext ps, int ncp, int corr_size, int precision, int flags) {
143
 
    int err;
 
230
static int dictSetupFFT(DICTContext ctx, ProcessingState ps, int ncp, int corr_size, int precision, int flags) {
 
231
    int err = 0;
144
232
    int base_blocks, side_blocks;
145
233
 
146
 
#ifdef DICT_HW_MEASURE_TIMINGS
147
 
    struct timeval tv1, tv2;
148
 
    gettimeofday(&tv1, NULL);
149
 
#endif /* DICT_HW_MEASURE_TIMINGS */
150
 
 
151
234
    fftFree(ps);
152
235
 
153
236
    ps->ncp = ncp;
188
271
    ps->base_blocks_power = get_power(base_blocks);
189
272
 
190
273
    ps->use_cache = 1;
 
274
 
 
275
    if (!ctx->use_threads) {
 
276
        err = fftInit(ps, device_memory);
 
277
        if ((err == DICT_ERROR_CUDA_MALLOC)&&(ps->use_cache)) {
 
278
            cudaGetLastError();
 
279
            ps->use_cache = 0;
 
280
            err = fftInit(ps, device_memory);
 
281
        }
 
282
    }
 
283
 
 
284
    return err;
 
285
}
 
286
 
 
287
#ifdef DICT_SUPPORT_THREADS
 
288
static int dictSetupThread(HWThread thr, void *hwctx, int device_id, void *data) {
 
289
    int err;
 
290
    DICTContext ctx = (DICTContext)data;
 
291
    
 
292
    ProcessingState ps = ctx->pstates[device_id];
 
293
 
191
294
    err = fftInit(ps, device_memory);
192
295
    if ((err == DICT_ERROR_CUDA_MALLOC)&&(ps->use_cache)) {
 
296
        cudaGetLastError();
193
297
        ps->use_cache = 0;
194
298
        err = fftInit(ps, device_memory);
195
299
    }
196
300
 
197
 
#ifdef DICT_HW_MEASURE_TIMINGS
198
 
    gettimeofday(&tv2, NULL);
199
 
    ps->time[1] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
200
 
#endif /* DICT_HW_MEASURE_TIMINGS */
201
 
 
202
 
    if (ps->use_cache) {
203
 
        reportMessage("Caching is enabled");
204
 
    } else {
205
 
        reportMessage("Caching is disabled");
206
 
    }
207
 
 
208
 
    return err;
209
 
}
210
 
 
211
 
int dictSetTemplatePoints(DICTContext ps, const float *points_x, const float *points_y) {
212
 
#ifdef DICT_HW_MEASURE_TIMINGS
213
 
    struct timeval tv1, tv2;
214
 
    gettimeofday(&tv1, NULL);
215
 
#endif /* DICT_HW_MEASURE_TIMINGS */
216
 
 
217
 
    memcpy(ps->points,                      points_x, ps->ncp * sizeof(float));
218
 
    memcpy(ps->points + ps->ncp_alloc_size, points_y, ps->ncp * sizeof(float));
219
 
 
220
 
#ifdef DICT_HW_MEASURE_TIMINGS
221
 
    gettimeofday(&tv2, NULL);
222
 
    ps->time[2] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
223
 
#endif /* DICT_HW_MEASURE_TIMINGS */
224
 
 
225
 
    return 0;
226
 
}
227
 
 
228
 
int dictSetDimensions(DICTContext ps, int width, int height) {
229
 
    if ((width != ps->width)||(height != ps->height)) {
230
 
        ps->width = width;
231
 
        ps->height = height;
232
 
 
233
 
        return fftSetupDimensions(ps);    
234
 
    }
235
 
    
236
 
    return 0;
237
 
}
238
 
 
239
 
int dictSetPointsBuffer(DICTContext ps, float *point_x, float *point_y) {
240
 
    ps->res_x = point_x;
241
 
    ps->res_y = point_y;
242
 
    
243
 
    return 0;
244
 
}
245
 
 
246
 
int dictSetCurrentPoints(DICTContext ps, const float *points_x, const float *points_y) {
247
 
#ifdef DICT_HW_MEASURE_TIMINGS
248
 
    struct timeval tv1, tv2;
249
 
    gettimeofday(&tv1, NULL);
250
 
#endif /* DICT_HW_MEASURE_TIMINGS */
251
 
 
252
 
    memcpy(ps->points + 2 * ps->ncp_alloc_size, points_x, ps->ncp * sizeof(float));
253
 
    memcpy(ps->points + 3 * ps->ncp_alloc_size, points_y, ps->ncp * sizeof(float));
254
 
 
255
 
#ifdef DICT_HW_MEASURE_TIMINGS
256
 
    gettimeofday(&tv2, NULL);
257
 
    ps->time[3] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
258
 
#endif /* DICT_HW_MEASURE_TIMINGS */
259
 
 
260
 
 
261
 
    ps->stored = 0;
262
 
 
263
 
    return 0;
264
 
}
265
 
 
266
 
int dictCompute(DICTContext ps) {
267
 
    int err;
268
 
    
269
 
#ifdef DICT_HW_MEASURE_TIMINGS
270
 
    struct timeval tv1, tv2;
271
 
    gettimeofday(&tv1, NULL);
272
 
#endif /* DICT_HW_MEASURE_TIMINGS */
273
 
 
274
 
    err = fftGetCurrentPoints(ps);
275
 
 
276
 
#ifdef DICT_HW_MEASURE_TIMINGS
277
 
    gettimeofday(&tv2, NULL);
278
 
    ps->time[12] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
279
 
#endif /* DICT_HW_MEASURE_TIMINGS */
280
 
    
281
 
    return err;
282
 
}
283
 
 
284
 
int dictGetCurrentPoints(DICTContext ps, float *res_x, float *res_y) {
285
 
    int err;
286
 
 
287
 
#ifdef DICT_HW_MEASURE_TIMINGS
288
 
    struct timeval tv1, tv2;
289
 
    gettimeofday(&tv1, NULL);
290
 
#endif /* DICT_HW_MEASURE_TIMINGS */
291
 
 
292
 
    err = fftGetCurrentPoints(ps);
 
301
    ps->status = err;
 
302
    
 
303
    return 0;
 
304
}
 
305
#endif /* DICT_SUPPORT_THREADS */
 
306
 
 
307
 
 
308
int dictSetup(DICTContext ctx, int ncp, int corr_size, int precision, int flags) {
 
309
    int i, icp;
 
310
    
 
311
    int err;
 
312
    cudaError cuda_err;
 
313
 
 
314
    int have_cache = 0;
 
315
 
 
316
    int ncp_alloc = calc_alloc(ncp, CP_BLOCK);
 
317
    int ncp_blocks;
 
318
    int blocks_alloc;
 
319
    int per_device;
 
320
 
 
321
#ifdef DICT_HW_MEASURE_TIMINGS
 
322
    struct timeval tv1, tv2;
 
323
    gettimeofday(&tv1, NULL);
 
324
#endif /* DICT_HW_MEASURE_TIMINGS */
 
325
 
 
326
    dictFree(ctx);
 
327
    
 
328
    if (flags&DICT_FLAGS_MATLAB_MODE) {
 
329
        ctx->matlab_mode = 1;
 
330
    } else {
 
331
        ctx->matlab_mode = 0;
 
332
    }
 
333
 
 
334
#ifdef DICT_SUPPORT_THREADS 
 
335
    if (flags&DICT_FLAGS_SINGLE_THREAD) {
 
336
        ctx->use_threads = 0;
 
337
    } else {
 
338
        ctx->use_threads = 1;
 
339
    }
 
340
#endif /* DICT_SUPPORT_THREADS */
 
341
 
 
342
    if (ctx->use_threads) {
 
343
        ncp_blocks = ncp_alloc / CP_BLOCK;
 
344
        blocks_alloc = calc_alloc(ncp_blocks, device_number);
 
345
        per_device = (blocks_alloc / device_number) * CP_BLOCK;
 
346
    } else {
 
347
        per_device = ncp_alloc;
 
348
    }
 
349
 
 
350
    ctx->ncp = ncp;
 
351
    ctx->ncp_alloc_size = ncp_alloc;
 
352
    ctx->ncp_per_device = per_device;
 
353
 
 
354
    cuda_err = cudaHostAlloc((void**)&ctx->points, 8 * ctx->ncp_alloc_size * sizeof(float), 0);
 
355
    if (cuda_err) {
 
356
        reportError("Page locked host memory allocation of 8*%u*float bytes for control points is failed", ctx->ncp_alloc_size);
 
357
        dictFree(ctx);
 
358
        return DICT_ERROR_MALLOC;
 
359
    }
 
360
    
 
361
    for (icp = 0; icp < ncp; icp += per_device) {
 
362
        i = icp / per_device;
 
363
        int device_ncp = min2(per_device, ncp - icp);
 
364
        ProcessingState ps = ctx->pstates[i];
 
365
 
 
366
        err = dictSetupFFT(ctx, ps, device_ncp, corr_size, precision, flags);
 
367
        if (err) return err;
 
368
    }
 
369
    
 
370
#ifdef DICT_SUPPORT_THREADS 
 
371
    if (ctx->use_threads) {
 
372
        hw_sched_schedule_task(ctx->sched, ctx, dictSetupThread);
 
373
        hw_sched_wait_task(ctx->sched);
 
374
    }
 
375
#endif /* DICT_SUPPORT_THREADS */
 
376
    
 
377
    for (icp = 0; icp < ncp; icp += per_device) {
 
378
        i = icp / per_device;
 
379
        ProcessingState ps = ctx->pstates[i];
 
380
 
 
381
        if (ps->status) return ps->status;
 
382
 
 
383
        ps->points = ctx->points + icp;
 
384
        ps->points_alloc_size = ctx->ncp_alloc_size;
 
385
 
 
386
        if (ps->use_cache) ++have_cache;
 
387
    }
 
388
 
 
389
#ifdef DICT_HW_MEASURE_TIMINGS
 
390
    gettimeofday(&tv2, NULL);
 
391
    ctx->time[1] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
 
392
#endif /* DICT_HW_MEASURE_TIMINGS */
 
393
 
 
394
    if (have_cache) {
 
395
        reportMessage("Caching is enabled for %i devices of %i", have_cache, i + 1);
 
396
    } else {
 
397
        reportMessage("Caching is disabled for all %i devices", i + 1);
 
398
    }
 
399
 
 
400
    return 0;
 
401
}
 
402
 
 
403
#ifdef DICT_SUPPORT_THREADS 
 
404
static int dictSetDimensionsThread(HWThread thr, void *hwctx, int device_id, void *data) {
 
405
    int err;
 
406
    DICTContext ctx = (DICTContext)data;
 
407
    ProcessingState ps = ctx->pstates[device_id];
 
408
 
 
409
    err = fftSetupDimensions(ps);
 
410
    ps->status = err;
 
411
    
 
412
    return 0;
 
413
}
 
414
#endif /* DICT_SUPPORT_THREADS */
 
415
 
 
416
int dictSetDimensions(DICTContext ctx, int width, int height) {
 
417
    int err = 0;
 
418
    
 
419
    int icp, ncp = ctx->ncp;
 
420
    int per_device = ctx->ncp_per_device;
 
421
 
 
422
    if ((width != ctx->width)||(height != ctx->height)) {
 
423
        int image_size = width * height;
 
424
        
 
425
        if (ctx->base_image) free(ctx->base_image);
 
426
        ctx->base_image = (unsigned char*)malloc(image_size * sizeof(uint8_t));
 
427
        if (!ctx->base_image) {
 
428
            reportError("Memory allocation of %u*%u*uint8_t bytes for DICT/base_image is failed", width, height);
 
429
            dictFree(ctx);
 
430
            return DICT_ERROR_MALLOC;
 
431
        }
 
432
 
 
433
        ctx->width = width;
 
434
        ctx->height = height;
 
435
 
 
436
        for (icp = 0; icp < ncp; icp += per_device) {
 
437
            int i = icp / per_device;
 
438
            ProcessingState ps = ctx->pstates[i];
 
439
            
 
440
            ps->width = width;
 
441
            ps->height = height;
 
442
 
 
443
            if (!ctx->use_threads) {
 
444
                err = fftSetupDimensions(ps);
 
445
                if (err) return err;
 
446
            }
 
447
        }
 
448
    }
 
449
 
 
450
 
 
451
#ifdef DICT_SUPPORT_THREADS 
 
452
    if (ctx->use_threads) {
 
453
        hw_sched_schedule_task(ctx->sched, ctx, dictSetDimensionsThread);
 
454
        hw_sched_wait_task(ctx->sched);
 
455
 
 
456
        CHECK_ERROR(err)
 
457
    }
 
458
#endif /* DICT_SUPPORT_THREADS */
 
459
    
 
460
    return err;
 
461
}
 
462
 
 
463
 
 
464
 
 
465
int dictSetTemplatePoints(DICTContext ctx, const float *points_x, const float *points_y) {
 
466
#ifdef DICT_HW_MEASURE_TIMINGS
 
467
    struct timeval tv1, tv2;
 
468
    gettimeofday(&tv1, NULL);
 
469
#endif /* DICT_HW_MEASURE_TIMINGS */
 
470
 
 
471
    memcpy(ctx->points,                       points_x, ctx->ncp * sizeof(float));
 
472
    memcpy(ctx->points + ctx->ncp_alloc_size, points_y, ctx->ncp * sizeof(float));
 
473
 
 
474
#ifdef DICT_HW_MEASURE_TIMINGS
 
475
    gettimeofday(&tv2, NULL);
 
476
    ctx->time[2] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
 
477
#endif /* DICT_HW_MEASURE_TIMINGS */
 
478
 
 
479
    return 0;
 
480
}
 
481
 
 
482
 
 
483
int dictSetPointsBuffer(DICTContext ctx, float *point_x, float *point_y) {
 
484
    int icp, ncp = ctx->ncp;
 
485
    int per_device = ctx->ncp_per_device;
 
486
    
 
487
    ctx->res_x = point_x;
 
488
    ctx->res_y = point_y;
 
489
    
 
490
    for (icp = 0; icp < ncp; icp += per_device) {
 
491
        int i = icp / per_device;
 
492
        ProcessingState ps = ctx->pstates[i];
 
493
 
 
494
        ps->res_x = point_x + icp;
 
495
        ps->res_y = point_y + icp;
 
496
    }
 
497
    
 
498
    return 0;
 
499
}
 
500
 
 
501
int dictSetCurrentPoints(DICTContext ctx, const float *points_x, const float *points_y) {
 
502
    int icp, ncp = ctx->ncp;
 
503
    int per_device = ctx->ncp_per_device;
 
504
 
 
505
#ifdef DICT_HW_MEASURE_TIMINGS
 
506
    struct timeval tv1, tv2;
 
507
    gettimeofday(&tv1, NULL);
 
508
#endif /* DICT_HW_MEASURE_TIMINGS */
 
509
 
 
510
    memcpy(ctx->points + 2 * ctx->ncp_alloc_size, points_x, ctx->ncp * sizeof(float));
 
511
    memcpy(ctx->points + 3 * ctx->ncp_alloc_size, points_y, ctx->ncp * sizeof(float));
 
512
 
 
513
#ifdef DICT_HW_MEASURE_TIMINGS
 
514
    gettimeofday(&tv2, NULL);
 
515
    ctx->time[3] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
 
516
#endif /* DICT_HW_MEASURE_TIMINGS */
 
517
 
 
518
    for (icp = 0; icp < ncp; icp += per_device) {
 
519
        int i = icp / per_device;
 
520
        ProcessingState ps = ctx->pstates[i];
 
521
 
 
522
        ps->stored = 0;
 
523
    }
 
524
 
 
525
    return 0;
 
526
}
 
527
 
 
528
#ifdef DICT_SUPPORT_THREADS 
 
529
static int dictComputeThread(HWThread thr, void *hwctx, int device_id, void *data) {
 
530
    int err;
 
531
    DICTContext ctx = (DICTContext)data;
 
532
    ProcessingState ps = ctx->pstates[device_id];
 
533
 
 
534
    err = fftGetCurrentPoints(ps);
 
535
    ps->status = err;
 
536
    
 
537
    return 0;
 
538
}
 
539
#endif /* DICT_SUPPORT_THREADS */
 
540
 
 
541
int dictCompute(DICTContext ctx) {
 
542
    int err = 0;
 
543
 
 
544
    int icp, ncp = ctx->ncp;
 
545
    int per_device = ctx->ncp_per_device;
 
546
    
 
547
#ifdef DICT_HW_MEASURE_TIMINGS
 
548
    struct timeval tv1, tv2;
 
549
    gettimeofday(&tv1, NULL);
 
550
#endif /* DICT_HW_MEASURE_TIMINGS */
 
551
    
 
552
    if (ctx->use_threads) {
 
553
#ifdef DICT_SUPPORT_THREADS 
 
554
        hw_sched_schedule_task(ctx->sched, ctx, dictComputeThread);
 
555
        hw_sched_wait_task(ctx->sched);
 
556
 
 
557
        CHECK_ERROR(err)
 
558
#endif /* DICT_SUPPORT_THREADS */
 
559
    } else {
 
560
        for (icp = 0; icp < ncp; icp += per_device) {
 
561
            int i = icp / per_device;
 
562
            ProcessingState ps = ctx->pstates[i];
 
563
            err = fftGetCurrentPoints(ps);
 
564
            if (err) break;
 
565
        }
 
566
    }
 
567
 
 
568
#ifdef DICT_HW_MEASURE_TIMINGS
 
569
    gettimeofday(&tv2, NULL);
 
570
    ctx->time[16] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
 
571
#endif /* DICT_HW_MEASURE_TIMINGS */
 
572
    
 
573
    return err;
 
574
}
 
575
 
 
576
int dictGetCurrentPoints(DICTContext ctx, float *res_x, float *res_y) {
 
577
    int err;
 
578
    int stored;
 
579
 
 
580
#ifdef DICT_HW_MEASURE_TIMINGS
 
581
    struct timeval tv1, tv2;
 
582
#endif /* DICT_HW_MEASURE_TIMINGS */
 
583
 
 
584
    err = dictCompute(ctx);
293
585
    if (err) return err;
294
586
 
295
 
    if ((res_x)&&(res_x != ps->res_x)) {
 
587
#ifdef DICT_HW_MEASURE_TIMINGS
 
588
    gettimeofday(&tv1, NULL);
 
589
#endif /* DICT_HW_MEASURE_TIMINGS */
 
590
    
 
591
        // stored is changed synchronously across devices
 
592
    stored = ctx->pstates[0]->stored;
 
593
 
 
594
    if ((res_x)&&(res_x != ctx->res_x)) {
296
595
        float *data_x;
297
 
        if (ps->stored) data_x = ps->res_x;
298
 
        else data_x = ps->points + 2 * ps->ncp_alloc_size;
 
596
        if (stored) data_x = ctx->res_x;
 
597
        else data_x = ctx->points + 2 * ctx->ncp_alloc_size;
299
598
        
300
 
        memcpy(res_x, data_x, ps->ncp * sizeof(float));
 
599
        memcpy(res_x, data_x, ctx->ncp * sizeof(float));
301
600
    }
302
601
 
303
 
    if ((res_y)&&(res_y != ps->res_y)) {
 
602
    if ((res_y)&&(res_y != ctx->res_y)) {
304
603
        float *data_y;
305
 
        if (ps->stored) data_y = ps->res_y;
306
 
        else data_y = ps->points + 3 * ps->ncp_alloc_size;
 
604
        if (stored) data_y = ctx->res_y;
 
605
        else data_y = ctx->points + 3 * ctx->ncp_alloc_size;
307
606
 
308
 
        memcpy(res_y, data_y, ps->ncp * sizeof(float));
 
607
        memcpy(res_y, data_y, ctx->ncp * sizeof(float));
309
608
    }
310
609
 
311
610
#ifdef DICT_HW_MEASURE_TIMINGS
312
611
    gettimeofday(&tv2, NULL);
313
 
    ps->time[16] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
 
612
    ctx->time[16] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
314
613
#endif /* DICT_HW_MEASURE_TIMINGS */
315
614
    
316
615
    return 0;
317
616
}
318
617
 
319
 
int dictLoadTemplateFragment(DICTContext ps, int icp, int ncp, const unsigned char *img) {
 
618
/*
 
619
static int dictLoadTemplateFragment(DICTContext ctx, int icp, int ncp, const unsigned char *img) {
320
620
    int err;
321
621
 
322
622
    err = fftLoadBaseImage(ps, img);
324
624
 
325
625
    return err;
326
626
}
327
 
 
328
 
int dictLoadTemplateImage(DICTContext ps, const unsigned char *img, int width, int height) {
 
627
*/
 
628
 
 
629
 
 
630
#ifdef DICT_SUPPORT_THREADS 
 
631
static int dictLoadTemplateImageThread(HWThread thr, void *hwctx, int device_id, void *data) {
329
632
    int err;
330
 
 
331
 
    int icp;
332
 
 
 
633
    DICTContext ctx = (DICTContext)data;
 
634
    ProcessingState ps = ctx->pstates[device_id];
 
635
 
 
636
    int jcp;
 
637
 
 
638
    err = fftLoadBaseImage(ps, ctx->param_img);
 
639
    
 
640
    if (ps->use_cache) {
 
641
        for (jcp = 0; (jcp < ps->ncp)&&(!err); jcp += CP_BLOCK) {
 
642
            err = fftLoadBaseFragment(ps, jcp, min2(CP_BLOCK, ps->ncp - jcp), ctx->param_img);
 
643
        }
 
644
    } else if (!ps->base_mode) ctx->res_do_copy = 1;
 
645
        
 
646
    ps->status = err;
 
647
 
 
648
    return 0;
 
649
}
 
650
#endif /* DICT_SUPPORT_THREADS */
 
651
 
 
652
int dictLoadTemplateImage(DICTContext ctx, const unsigned char *img, int width, int height) {
 
653
    int err = 0;
 
654
    int jcp;
 
655
    int icp, ncp = ctx->ncp;
 
656
    int per_device = ctx->ncp_per_device;
 
657
 
 
658
    int do_copy = 0;
 
659
    
333
660
#ifdef DICT_HW_MEASURE_TIMINGS
334
661
    struct timeval tv1, tv2;
335
662
    gettimeofday(&tv1, NULL);
336
663
#endif /* DICT_HW_MEASURE_TIMINGS */
337
664
 
338
 
    dictSetDimensions(ps, width, height);
339
 
 
340
 
    err = fftLoadBaseImage(ps, img);
341
 
    
342
 
    if (ps->use_cache) {
343
 
        for (icp = 0; (icp < ps->ncp)&&(!err); icp+=CP_BLOCK) {
344
 
            err = fftLoadBaseFragment(ps, icp, min2(CP_BLOCK, ps->ncp - icp), img);
 
665
    dictSetDimensions(ctx, width, height);
 
666
 
 
667
    if (ctx->use_threads) {
 
668
#ifdef DICT_SUPPORT_THREADS 
 
669
        ctx->res_do_copy = 0;
 
670
        ctx->param_img = img;
 
671
    
 
672
        hw_sched_schedule_task(ctx->sched, ctx, dictLoadTemplateImageThread);
 
673
        hw_sched_wait_task(ctx->sched);
 
674
 
 
675
        CHECK_ERROR(err)
 
676
    
 
677
        do_copy = ctx->res_do_copy;
 
678
#endif /* DICT_SUPPORT_THREADS */
 
679
    } else {
 
680
        for (icp = 0; icp < ncp; icp += per_device) {
 
681
            int i = icp / per_device;
 
682
            ProcessingState ps = ctx->pstates[i];
 
683
 
 
684
            err = fftLoadBaseImage(ps, img);
 
685
    
 
686
            if (ps->use_cache) {
 
687
                for (jcp = 0; (jcp < ps->ncp)&&(!err); jcp += CP_BLOCK) {
 
688
                    err = fftLoadBaseFragment(ps, jcp, min2(CP_BLOCK, ps->ncp - jcp), img);
 
689
                }
 
690
            } else if (!ps->base_mode) do_copy = 1;
 
691
        
 
692
            if (err) break;
345
693
        }
346
694
    }
347
695
 
 
696
    if (do_copy) {
 
697
        memcpy(ctx->base_image, img, width * height * sizeof(uint8_t));
 
698
    }
 
699
 
348
700
#ifdef DICT_HW_MEASURE_TIMINGS
349
701
    gettimeofday(&tv2, NULL);
350
 
    ps->time[6] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
 
702
    ctx->time[17] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
351
703
#endif /* DICT_HW_MEASURE_TIMINGS */
352
704
 
353
 
 
354
705
    return err;
355
706
}
356
707
 
357
708
 
358
 
int dictLoadFragment(DICTContext ps, int icp, int ncp, const unsigned char *input) {
 
709
static int dictLoadFragment(DICTContext ctx, ProcessingState ps, int icp, int ncp, const unsigned char *input) {
359
710
    int err;
360
711
    int load_base = !ps->use_cache;
361
712
 
366
717
#endif /* DICT_HW_MEASURE_TIMINGS */
367
718
 
368
719
    if (load_base) {
369
 
            // We are enforcing image mode if the cache is disabled
370
 
        err = fftLoadBaseFragment(ps, icp, ncp, ps->base_image);
 
720
        err = fftLoadBaseFragment(ps, icp, ncp, ctx->base_image);
371
721
        if (err) return err;
372
722
    }
373
723
 
384
734
    time[2] = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
385
735
#endif /* DICT_HW_MEASURE_TIMINGS */
386
736
 
387
 
    err = fftPreprocessFragment(ps, icp, min2(CP_BLOCK, ps->ncp - icp));
 
737
    err = fftPreprocessFragment(ps, icp, ncp);
388
738
    if (err) return err;
389
739
 
390
740
#ifdef DICT_HW_MEASURE_TIMINGS
392
742
    time[3] = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
393
743
#endif /* DICT_HW_MEASURE_TIMINGS */
394
744
 
395
 
    err = fftProcessFragment(ps, icp, min2(CP_BLOCK, ps->ncp - icp));
 
745
    err = fftProcessFragment(ps, icp, ncp);
396
746
    if (err) return err;
397
747
 
398
748
#ifdef DICT_HW_MEASURE_TIMINGS
400
750
    time[4] = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
401
751
#endif /* DICT_HW_MEASURE_TIMINGS */
402
752
 
403
 
    err = fftPostprocessFragment(ps, icp, min2(CP_BLOCK, ps->ncp - icp));
 
753
    err = fftPostprocessFragment(ps, icp, ncp);
404
754
    if (err) return err;
405
755
 
406
 
#ifdef DICT_HW_MEASURE_TIMINGS
 
756
# ifdef DICT_HW_MEASURE_TIMINGS
407
757
    gettimeofday(&tv2, NULL);
408
758
    time[5] = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
409
759
    
412
762
        time[i] -= time[i-1];
413
763
    }
414
764
    
415
 
    for (int i = 1; i < 6; i++) {
416
 
        ps->time[i+5] += time[i];
 
765
    if (!ctx->use_threads) {
 
766
        for (int i = 1; i < 6; i++) {
 
767
            ctx->time[i+5] += time[i];
 
768
        }
417
769
    }
418
 
#endif /* DICT_HW_MEASURE_TIMINGS */
419
 
 
420
 
        
421
 
        return 0;
 
770
# endif /* DICT_HW_MEASURE_TIMINGS */
 
771
 
 
772
 
 
773
    return 0;
422
774
}
423
775
 
424
 
int dictLoadImage(DICTContext ps, unsigned char *img) {
 
776
#ifdef DICT_SUPPORT_THREADS
 
777
static int dictLoadImageThread(HWThread thr, void *hwctx, int device_id, void *data) {
425
778
    int err;
426
 
    int ncp = ps->ncp;
427
 
 
428
 
#ifdef DICT_HW_MEASURE_TIMINGS
429
 
    struct timeval tv1, tv2;
430
 
    gettimeofday(&tv1, NULL);
431
 
#endif /* DICT_HW_MEASURE_TIMINGS */
432
 
 
433
 
    err = fftLoadImage(ps, img);
434
 
    if (err) return err;
435
 
 
436
 
#ifdef DICT_HW_MEASURE_TIMINGS
437
 
    gettimeofday(&tv2, NULL);
438
 
    ps->time[4] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
439
 
#endif /* DICT_HW_MEASURE_TIMINGS */
440
 
 
441
 
    for (int icp = 0; icp < ncp; icp+=CP_BLOCK) {
442
 
        err = dictLoadFragment(ps, icp, min2(CP_BLOCK, ps->ncp - icp), img);
443
 
        if (err) return err;
 
779
    DICTContext ctx = (DICTContext)data;
 
780
    ProcessingState ps = ctx->pstates[device_id];
 
781
 
 
782
    int jcp;
 
783
 
 
784
    err = fftLoadImage(ps, ctx->param_img);
 
785
    
 
786
    for (jcp = 0; (jcp < ps->ncp)&&(!err); jcp += CP_BLOCK) {
 
787
        err = dictLoadFragment(ctx, ps, jcp, min2(CP_BLOCK, ps->ncp - jcp), ctx->param_img);
444
788
    }
445
 
    
446
 
#ifdef DICT_HW_MEASURE_TIMINGS
447
 
    gettimeofday(&tv2, NULL);
448
 
    ps->time[5] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
449
 
#endif /* DICT_HW_MEASURE_TIMINGS */
 
789
 
 
790
    ps->status = err;
450
791
 
451
792
    return 0;
452
793
}
453
 
 
454
 
 
455
 
int dictProcessImage(DICTContext ps, unsigned char *img) {
456
 
    int err = dictLoadImage(ps, img);
457
 
    if (err) return err;
458
 
    return dictCompute(ps);
459
 
}
460
 
 
461
 
int dictLoadTemplateImageFile(DICTContext ps, const char *name) {
462
 
    int err = dictImageLoadTemplateImage(ps, name);
463
 
    if (err) return err;
464
 
    return dictLoadTemplateImage(ps, ps->image, ps->width, ps->height);
465
 
}
466
 
int dictLoadImageFile(DICTContext ps, const char *name) {
467
 
    int err = dictImageLoadImage(ps, name);
468
 
    if (err) return err;
469
 
    return dictLoadImage(ps, ps->image);
470
 
}
471
 
 
472
 
int dictProcessImageFile(DICTContext ps, const char *name) {
473
 
    int err = dictLoadImageFile(ps, name);
474
 
    if (err) return err;
475
 
    return dictCompute(ps);
 
794
#endif /* DICT_SUPPORT_THREADS */
 
795
 
 
796
 
 
797
 
 
798
int dictLoadImage(DICTContext ctx, const unsigned char *img) {
 
799
    int err = 0;
 
800
 
 
801
    int icp, ncp = ctx->ncp;
 
802
    int per_device = ctx->ncp_per_device;
 
803
 
 
804
    if (ctx->use_threads) {
 
805
#ifdef DICT_SUPPORT_THREADS
 
806
# ifdef DICT_HW_MEASURE_TIMINGS
 
807
        struct timeval tv1, tv2;
 
808
        gettimeofday(&tv1, NULL);
 
809
# endif /* DICT_HW_MEASURE_TIMINGS */
 
810
 
 
811
        ctx->param_img = img;
 
812
    
 
813
        hw_sched_schedule_task(ctx->sched, ctx, dictLoadImageThread);
 
814
        hw_sched_wait_task(ctx->sched);
 
815
 
 
816
        CHECK_ERROR(err)
 
817
# ifdef DICT_HW_MEASURE_TIMINGS
 
818
        gettimeofday(&tv2, NULL);
 
819
        ctx->time[5] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
 
820
# endif /* DICT_HW_MEASURE_TIMINGS */
 
821
#endif /* DICT_SUPPORT_THREADS */
 
822
    } else {
 
823
        for (icp = 0; icp < ncp; icp += per_device) {
 
824
            int i = icp / per_device;
 
825
            ProcessingState ps = ctx->pstates[i];
 
826
 
 
827
#ifdef DICT_HW_MEASURE_TIMINGS
 
828
            struct timeval tv1, tv2;
 
829
            gettimeofday(&tv1, NULL);
 
830
#endif /* DICT_HW_MEASURE_TIMINGS */
 
831
 
 
832
            err = fftLoadImage(ps, img);
 
833
 
 
834
#ifdef DICT_HW_MEASURE_TIMINGS
 
835
            gettimeofday(&tv2, NULL);
 
836
            ctx->time[4] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
 
837
#endif /* DICT_HW_MEASURE_TIMINGS */
 
838
 
 
839
            for (int jcp = 0; (jcp < ps->ncp)&&(!err); jcp += CP_BLOCK) {
 
840
                err = dictLoadFragment(ctx, ps, jcp, min2(CP_BLOCK, ps->ncp - jcp), img);
 
841
            }
 
842
    
 
843
#ifdef DICT_HW_MEASURE_TIMINGS
 
844
            gettimeofday(&tv2, NULL);
 
845
            ctx->time[5] += (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
 
846
#endif /* DICT_HW_MEASURE_TIMINGS */
 
847
        }
 
848
    }
 
849
 
 
850
    return err;
 
851
}
 
852
 
 
853
int dictLoadTemplateImageFile(DICTContext ctx, const char *name) {
 
854
    int err = dictImageLoadTemplateImage(ctx, name);
 
855
    if (err) return err;
 
856
    return dictLoadTemplateImage(ctx, ctx->image, ctx->width, ctx->height);
 
857
}
 
858
 
 
859
int dictLoadImageFile(DICTContext ctx, const char *name) {
 
860
    int err = dictImageLoadImage(ctx, name);
 
861
    if (err) return err;
 
862
    return dictLoadImage(ctx, ctx->image);
 
863
}
 
864
 
 
865
int dictProcessImage(DICTContext ctx, const unsigned char *img) {
 
866
    int err = dictLoadImage(ctx, img);
 
867
    if (err) return err;
 
868
    return dictCompute(ctx);
 
869
}
 
870
 
 
871
int dictProcessImageFile(DICTContext ctx, const char *name) {
 
872
    int err = dictLoadImageFile(ctx, name);
 
873
    if (err) return err;
 
874
    return dictCompute(ctx);
476
875
}