Use memset to Avoid Loops in C
The Usage of memset
memset has the following definition,
void* memset(void* s, int c, size_t n);
The method set each of the first n bytes of memory pointed by s to c and return s. Note that although the second parameter has type of int, it’s converted to unsigned char before the memory operation is carried out. Therefore, c has to be in the range of [0, 255].
memset works on bytes. If you use memset for array of ints, or doubles, most of the case it won’t work. memset works on the following situations (there may be more cases),
- initialize char, int, float arrays to 0s.
- initialize char to any arbitrary value.
- initialize int to values with same byte value for all 4 bytes. (e.g. 0×01010101 = 16843009)
But we seldom encounter this case.
memset and C Arrays
If the array is static, the memory is allocated at stack. The memory is continuous for both 1-D and multi-dimensional arrays.
If the array is dynamic, the memory is allocated at heap. If you’re allocating array memory using malloc, malloc can only assue the memory allocated on each call is continous. So if the array allocated is 1-D, the memory is continuous, otherwise, it’s not guaranteed (since you’re calling malloc multiple times).
memset works on a block of continuous memory. For static array, say int a[10][10], you can simply use memset(a, 0, sizeof(a[0][0])*10*10) to initialize all elements to 0. For dynamic array, the example below gives the idea,
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
int **a;
int i, j;
a = (int **)malloc(sizeof(int *)*10);
for (i = 0; i < 10; ++i) {
a[i] = (int*)malloc(sizeof(int)*10);
}
//memset to all 0s
for (i = 0; i < 10; ++i) {
memset(a[i], 0, sizeof(a[i][0])*10);
}
//print out the value
for (i = 0; i < 10; ++i) {
for (j = 0; j < 10; ++j) {
printf("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
Essentially, one memset is needed for one malloc.
Use memset instead of Loops
memset is usually optimized by compilers to produce more efficient binary code than loops. Below is a testing code to compare the performance of loop initialization and memset.
/*
this is a small test program tests which method to get the file size is faster
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define D1 50
#define D2 90
#define D3 90
unsigned char (*pData)[D1][D2][D3];
unsigned char data1[D1][D2][D3];
unsigned char data2[D1][D2][D3];
int main() {
struct timeval stTime, edTime;
int LOOP_COUNT = 100;
int cnt, i, j, k;
memset(data1, 0x01, D1*D2*D3);
memset(data2, 0x00, D1*D2*D3);
pData = &data1;
//using memset
gettimeofday(&stTime, NULL);
/*for (cnt = 0; cnt < LOOP_COUNT; ++cnt) {
for (i = 0; i < D1; ++i) {
for (j = 0; j < D2; ++j) {
memset(&(*pData)[i][j][0], 1, sizeof(unsigned char)*D3);
}
}
}*/
for (cnt = 0; cnt < LOOP_COUNT; ++cnt) {
memset(&(*pData[0][0][0]), 1, sizeof(unsigned char)*D1*D2*D2);
}
gettimeofday(&edTime, NULL);
printf("%u:%u\n", (unsigned int)(edTime.tv_sec - stTime.tv_sec), (unsigned int)(edTime.tv_usec - stTime.tv_usec));
//using loop
pData = &data2;
gettimeofday(&stTime, NULL);
for (cnt = 0; cnt < LOOP_COUNT; ++cnt) {
for (i = 0; i < D1; ++i) {
for (j = 0; j < D2; ++j) {
for (k = 0; k < D3; ++k) {
(*pData)[i][j][k] = 1;
}
}
}
}
gettimeofday(&edTime, NULL);
printf("%u:%u\n", (unsigned int)(edTime.tv_sec - stTime.tv_sec), (unsigned int)(edTime.tv_usec - stTime.tv_usec));
//(*pData)[_stFrame][_edH][_edW] = 88; //uncomment see it fails the check below
//to check two methods get same results
for (i = 0; i < D1; ++i) {
for (j = 0; j < D2; ++j) {
for (k = 0; k < D3; ++k) {
if (data1[i][j][k] != data2[i][j][k]) {
printf("it doesn't work\n");
return;
}
}
}
}
}
Compile the code with “gcc -o test test.c” and run the code with “./test” on a Levono Laptop Dual Core 2.0 GHz, 3G memory Ubuntu 10.04 system gives the results below,
0:6470
0:121570
memset is almost 20 times as fast as the loop method. Note that the commented code contains a test for doing memset for only the inner most loop, it actually still beats the loop method. This means even for dynamic allocated array which we can only use memset for inner most loop, it can still improve the performance over all loops method.
References:
Arrays and Pointers: http://www.lysator.liu.se/c/c-faq/c-2.html
Leave a Reply Cancel reply
40% Discount on My Book — Android NDK Cookbook
Android NDK Cookbook ebook 40% discount with promotion code MREANC40 at Packt Publishing The promotion code is valid until 15th June.Categories
- Android Apps (18)
- Android Audio Editor (1)
- TS 2 (3)
- Video Converter Android (8)
- Video2Gif (1)
- Android Tutorial (26)
- Android Dev Tools (1)
- API illustrated (8)
- Multimedia API (3)
- ffmpeg on Android (4)
- NDK (6)
- UI (5)
- Animation (1)
- Code Snippet (2)
- Coding Beyond Technique (18)
- a word, a world (4)
- Bug Rectified (4)
- Programming Habit (1)
- Software as a Career (1)
- Software as User Experience (1)
- Compilers and Related (2)
- ELF (2)
- Computer Languages (31)
- C/C++ (13)
- Java (9)
- JavaScript (2)
- PHP (1)
- Python (8)
- Data Structure & Algorithms (29)
- Bits (1)
- Data Structure (5)
- Integers (10)
- BigInteger (1)
- Prime (4)
- Search (3)
- Sorting (5)
- Strings (5)
- Database (1)
- SQLite (1)
- Digital Signal Processing (33)
- Distributed Systems (17)
- Apache Cassandra (6)
- Apache Hadoop (8)
- Apache Avro (3)
- Apache Nutch (3)
- Apache Solr (1)
- Linux Study Notes (40)
- crontab (1)
- Linux Kernel Programming (8)
- Linux Programming (12)
- IPC (2)
- Linux Network Programming (5)
- Linux Signals (2)
- Linux Shell Scripting (1)
- ssh (3)
- Machinery (30)
- misc (1)
- My Ideas (1)
- My Project (3)
- Mobile Caching (1)
- Selective Decoding (2)
- My Publication (1)
- My Readings (1)
- Networking (15)
- Program for Performance (8)
- Uncategorized (1)
- Virtual Machine (2)
- Web Dev (8)
- web components (3)
- Android Apps (18)
Recent Comments
Archives
- May 2013 (1)
- April 2013 (1)
- March 2013 (4)
- December 2012 (2)
- November 2012 (6)
- October 2012 (6)
- September 2012 (3)
- August 2012 (13)
- July 2012 (15)
- June 2012 (3)
- May 2012 (8)
- April 2012 (4)
- March 2012 (13)
- February 2012 (19)
- January 2012 (9)
- December 2011 (11)
- November 2011 (12)
- October 2011 (4)
- September 2011 (12)
- August 2011 (16)
- July 2011 (15)
- June 2011 (6)
- May 2011 (10)
- April 2011 (13)
- March 2011 (20)
- February 2011 (4)
- November 2010 (2)
- May 2010 (1)
- April 2010 (1)
- February 2010 (1)




