我想在一个单独的线程中写输出,我知道这可以完成
>异步I / O.
>创建线程
> I / O完成端口
我有两类问题,即概念和特定代码.
概念性问题
什么是最好的方法.请注意,应用程序应该可以移植到Linux,但是,我不知道这对于我选择的1-3是多么重要,因为我会编写一个关于任何内核/ API特定的包装器.对我来说,最重要的标准是速度.我已经读过,选项1不太可能提高程序的性能,并且内核在任何情况下都会为i / o操作创建新的线程,所以为什么不立即使用选项(2),看起来好像很有用更容易编程(因为我没有使用选项(1)成功,请参阅下面的代码问题).
请注意,我阅读了https://stackoverflow.com/questions/3689759/how-can-i-run-a-specific-function-of-thread-asynchronously-in-c-c,但是根据应用程序的性质,我没有看到使用内容的动机.所以我希望有人能给我一些建议,在我的情况下最好.同样来自Johnson M. Hart的“Windows系统编程”一书,我知道建议使用线程,主要是因为它的简单性.但是,它也会最快吗?
代码问题
这个问题涉及到目前为止我为使异步I / O工作所做的尝试.我知道它是一个很大的代码,所以它不容易调查.无论如何,我真的很感激任何尝试.
为了减少执行时间,我尝试使用带有重叠结构的FILE_FLAGGED_OVERLAP的CreateFile()使用WINAPI通过新线程编写输出.我已经创建了一个示例程序,我试图让它工作.但是,我遇到了两个问题:
>当我删除已存在的文件时,文件仅以重叠模式打开(我尝试在不同模式下使用CreateFile(CREATE_ALWAYS,CREATE_NEW,OPEN_EXISTING),但这没有用).
>只有第一个WriteFile异步执行. WriteFile命令的其余部分是同步的.对于这个问题,我已经咨询了http://support.microsoft.com/kb/156932.似乎我遇到的问题与“对文件的任何写操作扩展其长度都是同步的”这一事实有关.我已经尝试通过增加文件大小/有效数据大小(代码中的注释区域)来解决这个问题.但是,我仍然没有让它发挥作用.我知道可能的情况是,为了最大限度地利用FILE_FLAG_NO_BUFFERING创建具有FILE_FLAG_NO_BUFFERING的异步io,但是我无法使其工作.
请注意,程序在执行路径中创建一个大约120mb的文件.另请注意,打印报表“不行”是不可取的,我希望看到“可以在后台工作”出现在我的屏幕上……这里出了什么问题?
#include <windows.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #define ASYNC // remove this definition to run synchronously (i.e. using fwrite) #ifdef ASYNC struct _OVERLAPPED *pOverlapped; HANDLE *pEventH; HANDLE *pFile; #else FILE *pFile; #endif #define DIM_X 100 #define DIM_Y 150000 #define _PRINTERROR(msgs)\ {printf("file: %s,line: %d,%s",__FILE__,__LINE__,msgs);\ fflush(stdout);\ return 0;} \ #define _PRINTF(msgs)\ {printf(msgs);\ fflush(stdout);} \ #define _START_TIMER \ time_t time1,time2; \ clock_t clock1; \ time(&time1); \ printf("start time: %s",ctime(&time1)); \ fflush(stdout); #define _END_TIMER\ time(&time2);\ clock1 = clock();\ printf("end time: %s",ctime(&time2));\ printf("elapsed processor time: %.2f\n",(((float)clock1)/CLOCKS_PER_SEC));\ fflush(stdout); double aio_dat[DIM_Y] = {0}; double do_compute(double A,double B,int arr_len); int main() { _START_TIMER; const char *pName = "test1.bin"; DWORD dwBytesToWrite; BOOL bErrorFlag = FALSE; int j=0; int i=0; int fOverlapped=0; #ifdef ASYNC // create / open the file pFile=CreateFile(pName,GENERIC_WRITE,// open for writing 0,// share write access NULL,// default security CREATE_ALWAYS,// create new/overwrite existing FILE_FLAG_OVERLAPPED,// | FILE_FLAG_NO_BUFFERING,// overlapped file NULL); // no attr. template // check whether file opening was ok if(pFile==INVALID_HANDLE_VALUE){ printf("%x\n",GetLastError()); _PRINTERROR("file not opened properly\n"); } // make the overlapped structure pOverlapped = calloc(1,sizeof(struct _OVERLAPPED)); pOverlapped->Offset = 0; pOverlapped->OffsetHigh = 0; // put event handle in overlapped structure if(!(pOverlapped->hEvent = CreateEvent(NULL,TRUE,FALSE,NULL))){ printf("%x\n",GetLastError()); _PRINTERROR("error in createevent\n"); } #else pFile = fopen(pName,"wb"); #endif // create some output for(j=0;j<DIM_Y;j++){ aio_dat[j] = do_compute(i,j,DIM_X); } // determine how many bytes should be written dwBytesToWrite = (DWORD)sizeof(aio_dat); for(i=0;i<DIM_X;i++){ // do this DIM_X times #ifdef ASYNC //if(i>0){ //SetFilePointer(pFile,dwBytesToWrite,NULL,FILE_CURRENT); //if(!(SetEndOfFile(pFile))){ // printf("%i\n",pFile); // _PRINTERROR("error in set end of file\n"); //} //SetFilePointer(pFile,-dwBytesToWrite,FILE_CURRENT); //} // write the bytes if(!(bErrorFlag = WriteFile(pFile,aio_dat,pOverlapped))){ // check whether io pending or some other error if(GetLastError()!=ERROR_IO_PENDING){ printf("lasterror: %x\n",GetLastError()); _PRINTERROR("error while writing file\n"); } else{ fOverlapped=1; } } else{ // if you get here output got immediately written; bad! fOverlapped=0; } if(fOverlapped){ // do background,this msgs is what I want to see for(j=0;j<DIM_Y;j++){ aio_dat[j] = do_compute(i,DIM_X); } for(j=0;j<DIM_Y;j++){ aio_dat[j] = do_compute(i,DIM_X); } _PRINTF("can do work in background\n"); } else{ // not overlapped,this message is bad _PRINTF("not ok\n"); } // wait to continue if((WaitForSingleObject(pOverlapped->hEvent,INFINITE))!=WAIT_OBJECT_0){ _PRINTERROR("waiting did not succeed\n"); } // reset event structure if(!(ResetEvent(pOverlapped->hEvent))){ printf("%x\n",GetLastError()); _PRINTERROR("error in resetevent\n"); } pOverlapped->Offset+=dwBytesToWrite; #else fwrite(aio_dat,sizeof(double),DIM_Y,pFile); for(j=0;j<DIM_Y;j++){ aio_dat[j] = do_compute(i,DIM_X); } for(j=0;j<DIM_Y;j++){ aio_dat[j] = do_compute(i,DIM_X); } #endif } #ifdef ASYNC CloseHandle(pFile); free(pOverlapped); #else fclose(pFile); #endif _END_TIMER; return 1; } double do_compute(double A,int arr_len) { int i; double res = 0; double *xA = malloc(arr_len * sizeof(double)); double *xB = malloc(arr_len * sizeof(double)); if ( !xA || !xB ) abort(); for (i = 0; i < arr_len; i++) { xA[i] = sin(A); xB[i] = cos(B); res = res + xA[i]*xA[i]; } free(xA); free(xB); return res; }
有用的链接
> http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/cref_cls/common/cppref_asynchioC_aio_read_write_eg.htm
> http://www.ibm.com/developerworks/linux/library/l-async/?ca=dgr-lnxw02aUsingPOISIXAIOAPI
> http://www.flounder.com/asynchexplorer.htm#Asynchronous%20I/O
我知道这是一个很大的问题,我想提前感谢所有人,他们在阅读它时遇到了麻烦,甚至可能会做出回应!