Skip to content

Commit 41fb824

Browse files
committed
allocate CPU quant data buffer just if needed
In the most eligible scenario, when using restart intervals, the Huffman coder is run on GPU and the data are used from there without need to copy to CPU memory. The CPU buffer is using pinned memory , which: 1. occupies needlessly some RAM space (non-swapable, so physically occupied) - 2 x PIX_COUNT x CHANNELS B 2. the allocation of pinned memory takes some amount of time - for 4K 24-bit picture it is about 5-10 ms (Linux) depending on the HW but when encoding single large image it can be significant
1 parent 498c776 commit 41fb824

4 files changed

Lines changed: 37 additions & 7 deletions

File tree

src/gpujpeg_common.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,21 @@ reset_timers(struct gpujpeg_coder* coder)
562562
GPUJPEG_CUSTOM_TIMER_RESET(coder->duration_in_gpu);
563563
}
564564

565+
int
566+
gpujpeg_coder_allocate_cpu_huffman_buf(struct gpujpeg_coder * coder) {
567+
cudaMallocHost((void**)&coder->data_quantized, coder->data_size * sizeof(int16_t));
568+
gpujpeg_cuda_check_error("Coder quantized data host allocation", return -1);
569+
570+
int16_t* comp_data_quantized = coder->data_quantized;
571+
for ( int comp = 0; comp < coder->param.comp_count; comp++ ) {
572+
struct gpujpeg_component* component = &coder->component[comp];
573+
component->data_quantized = comp_data_quantized;
574+
comp_data_quantized += (size_t) component->data_width * component->data_height;
575+
}
576+
577+
return 0;
578+
}
579+
565580
size_t
566581
gpujpeg_coder_init_image(struct gpujpeg_coder * coder, const struct gpujpeg_parameters * param, const struct gpujpeg_image_parameters * param_image, cudaStream_t stream)
567582
{
@@ -853,13 +868,12 @@ gpujpeg_coder_init_image(struct gpujpeg_coder * coder, const struct gpujpeg_para
853868
cudaMalloc((void**)&coder->d_data, (coder->data_size + idct_overhead) * sizeof(uint8_t));
854869
gpujpeg_cuda_check_error("Coder data device allocation", return 0);
855870

856-
// (Re)allocated DCT and quantizer data in host memory
857-
if (coder->data_quantized != NULL) {
871+
// Deallocate DCT and quantizer data in host memory, alloc just if needed
872+
// (gpujpeg_coder_allocate_cpu_huff_data())
873+
if ( coder->data_quantized != NULL ) {
858874
cudaFreeHost(coder->data_quantized);
859875
coder->data_quantized = NULL;
860876
}
861-
cudaMallocHost((void**)&coder->data_quantized, coder->data_size * sizeof(int16_t));
862-
gpujpeg_cuda_check_error("Coder quantized data host allocation", return 0);
863877

864878
// (Re)allocated DCT and quantizer data in device memory
865879
if (coder->d_data_quantized != NULL) {
@@ -882,17 +896,14 @@ gpujpeg_coder_init_image(struct gpujpeg_coder * coder, const struct gpujpeg_para
882896
// Set data buffer to color components
883897
uint8_t* d_comp_data = coder->d_data;
884898
int16_t* d_comp_data_quantized = coder->d_data_quantized;
885-
int16_t* comp_data_quantized = coder->data_quantized;
886899
unsigned int data_quantized_index = 0;
887900
for ( int comp = 0; comp < coder->param.comp_count; comp++ ) {
888901
struct gpujpeg_component* component = &coder->component[comp];
889902
component->d_data = d_comp_data;
890903
component->d_data_quantized = d_comp_data_quantized;
891904
component->data_quantized_index = data_quantized_index;
892-
component->data_quantized = comp_data_quantized;
893905
d_comp_data += component->data_width * component->data_height;
894906
d_comp_data_quantized += component->data_width * component->data_height;
895-
comp_data_quantized += component->data_width * component->data_height;
896907
data_quantized_index += component->data_width * component->data_height;
897908
}
898909

src/gpujpeg_common_internal.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,15 @@ gpujpeg_coder_init(struct gpujpeg_coder* coder);
393393
size_t
394394
gpujpeg_coder_init_image(struct gpujpeg_coder * coder, const struct gpujpeg_parameters * param, const struct gpujpeg_image_parameters * param_image, cudaStream_t stream);
395395

396+
/**
397+
* @brief allocate buffers for CPU Huffman coder
398+
* Separated from gpujpeg_coder_init_image() - called only if needed, which is not normally so (using GPU Huffman
399+
* coder if restart intervals are not disabled).
400+
* @return 0 if succeeds, otherwise nonzero
401+
*/
402+
int
403+
gpujpeg_coder_allocate_cpu_huffman_buf(struct gpujpeg_coder * coder);
404+
396405
/**
397406
* Returns duration statistics for last coded image
398407
*/

src/gpujpeg_decoder.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,11 @@ gpujpeg_decoder_decode(struct gpujpeg_decoder* decoder, uint8_t* image, size_t i
265265
// Perform huffman decoding on CPU (when there are not enough segments to saturate GPU)
266266
if (coder->segment_count < 32 || unsupp_gpu_huffman_params) {
267267
GPUJPEG_CUSTOM_TIMER_START(coder->duration_huffman_coder, coder->param.perf_stats, decoder->stream, return -1);
268+
if (coder->data_quantized == NULL) {
269+
if (gpujpeg_coder_allocate_cpu_huffman_buf(coder) != 0) {
270+
return -1;
271+
}
272+
}
268273
if (0 != gpujpeg_huffman_cpu_decoder_decode(decoder)) {
269274
fprintf(stderr, "[GPUJPEG] [Error] Huffman decoder failed!\n");
270275
return -1;

src/gpujpeg_encoder.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,11 @@ gpujpeg_encoder_encode(struct gpujpeg_encoder* encoder, const struct gpujpeg_par
502502
// Perform huffman coding on CPU (when restart interval is not set)
503503
if ( coder->param.restart_interval == 0 ) {
504504
GPUJPEG_CUSTOM_TIMER_START(coder->duration_memory_from, coder->param.perf_stats, encoder->stream, return -1);
505+
if (coder->data_quantized == NULL) {
506+
if (gpujpeg_coder_allocate_cpu_huffman_buf(coder) != 0) {
507+
return -1;
508+
}
509+
}
505510
// Copy quantized data from device memory to cpu memory
506511
cudaMemcpyAsync(coder->data_quantized, coder->d_data_quantized, coder->data_size * sizeof(int16_t), cudaMemcpyDeviceToHost, encoder->stream);
507512

0 commit comments

Comments
 (0)